Hi everyone!
We recently merged a large change to js_of_ocaml that implements a new global dead code elimination pass. I wrote the following blog post which explains the impact of this change, why it was necessary, and all the important implementation details:
In a nutshell, this change addresses a long-known limitation of js_of_ocaml to remove unused code from functors (like Map and Set). Previously, even if only one function from these modules was used, all of the function definitions would be included in the JavaScript executable, significantly increasing the output size.
In practice, programs that compile with js_of_ocaml and depend on libraries that expose large functor interfaces (like TyXML, for instance) could see significant decreases in output size. In particular, for a minimal website using tyxml, we saw a decrease by 21kb or 11% of the total JS size. Websites using Map and Set could also see size decreases of up to 10kb for each module.
The new pass is enabled by default, and from our benchmarking, it shouldn’t contribute a significant increase in compile time for most programs (as in, less than 100ms). However, some very large projects (like ocamlc
or the OCaml toplevel compiler) could see a compile time increase of 1-5%. If this is significant, the pass can be disabled with --disable globaldeadcode
.
Thank you to Tarides for supporting this work through my internship, and in particular to my incredible mentors @vouillon , @otini and @jmid . Also thanks to @hhugo for reviewing and providing feedback on the pull request.