In theory, static typing would correct the biggest performance issues in JS (use monomorphic functions, don't mutate objects, and limit arrays of just one primitive/object type).
In practice, TypeScript allows and encourages you to create types that are horrendous for performance.
I'd love to see a comparison using AssemblyScript (basically stricter TS for WASM). I'd bet it's nearly the same speed as Rust while still being a third of the size.
This is a pretty good rundown of expected comparisons, but I doubt there will be any surprises here.
but the core loop in Rust is pretty straightforward. It could have been shortened and optimized further.
Also keep in mind that the larger the project, the harder it gets to keep JS in the performance sweet spot without tipping over any JIT heuristic, using GC, or accidentally causing a perf cliff, while the Rust has pretty stable and deterministic optimizations and keeps its memory management control at any scale.
It was my understanding that the V8 GC frankly was rarely used, and that they generally just let memory pile up quite a lot before it's used, in the hopes that it may never have to be run during application lifetime.
A quick profiling seemed to indicate that just a bit less than 10% of the JS time is being spent on the DOM rather than the calculations at hand. I wonder how much of that could be reclaimed simply by running the calculation in a web worker.
I suspect the bitwise AND operator every loop is another big performance issue. Normally, the JIT would leave the loop iterator as a 31-bit int, but because it is stored in a shared object, I suspect it must (f64 -> i31 -> AND -> f64) every time. A local variable that updates the object variable every 64ms and resets to zero would probably be faster.
The decPixel function should use a switch statement with values of 0, 1, 255, and default so it only needs to branch one time. This is probably a decent performance win too as around 15-20% of all time is spent here.
EDIT: I should praise the author for using a ternary instead of Math.max() as very few people know that the ternary is literally 100x faster. I wonder why this optimization was never made as it seems common enough.
https://www.measurethat.net/Benchmarks/Show/6528/0/mathmin-v...
I'm trying to work out how my interpretation of the calculations (in JS)[1] compare with the authors code, but trying to measure performance in CodePen is ... difficult to work out. My approach was to: 1. Run the CodePen with the inspector open; 2. Start recording performance; 3. Right click on the display panel and select 'Reload Frame'; 4: Stop recording performance after the images reappear.
... But when I look at the results nothing is making sense. Clearly my approach was wrong.
It would probably have to recognize that the _usage_ of this function can be translated into a local mutation without allocating additional arrays. But from just looking at the function locally it isn't clear whether that is a safe assumption.