Compressing the runtime (and JS) with roadroller

I just came across this processor intensive but highly effective compressor and as this is a topic I am interested in I am posting it here. The astonishing thing about this little piece of code is that it even compresses already minified and closure compiler treated JavaScript. Only downside… unpacking the code takes a (sometimes noticeable) slice of CPU time.

So, let us put the runtime in there:
The full runtime (HYPE-736.full.min.js) can be squashed to fit in 43kb from originally being 93kb.
The thin runtime (HYPE-736.thin.min.js) can be squashed to fit in 27kb from originally being 57kb.

Hype Compressor ZIP edition only gets the runtime down to 66kb (including the decompressor).

Check it out here:
https://lifthrasiir.github.io/roadroller/

2 Likes

I just tried compressing a 550kb hype_generated_script.js file and brought it down to 91kb (using 12 contexts being the default). At that point, the noticeable decompression lag is unbearable. Being around 5 seconds :frowning: (on an 2019 iMac i9). Still, impressive what can be done with computation, but not really usable. One still could play with the settings on roadroller to find a middle ground between compression and computation.

Update: Just added a screenshot above. The context setting offers a good way to balance computation and compression. Have fun… I use 3-4 and got good compromises.

Update2: I found that using my ZIP compression method is as efficient if the computational overhead is considered. As discussed in Hype Compressor, that approach isn't really needed if the server runs a proper GZIP header. But still interesting to play around with.

That's pretty cool, I hadn't seen it before!

Definitely be aware that its usage of eval() - this usually means that browsers cannot use JIT compilation and fallback to slower execution methods for all the code.

1 Like

These days, isn't that considered the same as crossing the streams in Ghostbusters? :stuck_out_tongue_winking_eye:

Well, the Function constructor is certainly preferred for dynamic functions.

  • The Function constructor creates a new Function object.
  • Calling the constructor directly can create functions dynamically, but suffers from security and similar (but far less significant) performance issues to Global_Objects/eval.
  • Invoking the Function constructor as a function has the same effect as invoking it as a constructor.


But the Hype runtime also uses eval for all the Hype functions you write in the editor. In the recently released Hype Bundles I extract the functions into the window scope, adding debugging and more in the process.

1 Like

Hello, I'm the author of Roadroller. I've noticed this thread from Google search and want to clarify a few points.

I have been asked about this before, but I do not recommend Roadroller as a generic compression tool. Especially because virtually every modern browser supports Brotli compression in HTTP (Content-Encoding: br). Brotli is less effective than Roadroller but much better than ZIP/DEFLATE and therefore good enough to be useful. Using only 3 or 4 context models is a good idea and places Roadroller roughly on par with Brotli, but then there is no reason to avoid Brotli at all. It is highly likely that your favorite CDN already supports Brotli behind the scene.

On the other hand I think this is false. The technical term is deoptimization, which is triggered when the JS engine is executing an optimized machine code and noticed something unexpected or hard to execute efficiently, in this case a call to eval(). However Roadroller only calls eval once, and as long as the resulting code doesn't call eval again the code remains static and the engine will soon pick it up again for JIT compilation. Therefore Roadroller's use of eval is one of (rare) happy cases.

1 Like

Totally, it is still fun to play around with it.

As you can read, I agree with you.
But still interesting to play around with compression and your approach.

Thanks for taking the time to provide some feedback and the tool!