Tarides Logo
a 3D render of the code snippet 'hello world' on a browser search bar against a multi-coloured background

The First Wasm_of_ocaml Release is Out!

Olivier Nicole

Senior Software Engineer

Isabella Leandersson

Communications Officer

Posted on Wed, 19 Feb 2025

The first feature-complete release of Wasm_of_OCaml (also known as WSOO) is out! A low-level virtual machine and portable compilation target, Wasm is popular with many developers thanks to its flexibility and wide compatibility.

We introduced you to Wasm and the benefits of bringing support for it to OCaml in our blog post on it in 2023. Since then, Wasm_of_ocaml has undergone new developments, so let’s take a look at what’s new and give you an overview of the release.

What is Wasm_of_ocaml?

Let’s start with a quick recap. Wasm_of_ocaml is a fork of the popular Js_of_ocaml compiler, translating OCaml bytecode to WebAssembly. It is web-oriented and relies on a JavaScript environment, and is designed to be an alternative to Js_of_ocaml. Since WebAssembly provides a sandboxed environment and enforces memory safety it is well-suited for security-critical applications, such as blockchain applications and programs running in the cloud. We plan to target these environments in the future.

Wasm_of_ocaml builds on the WebAssembly garbage collection extension (WasmGC), which is available by default on Chrome, Safari, and Firefox. This design means we don’t need to reimplement a garbage collector, and - as an added benefit - gives us good interoperability with JavaScript. Js_of_ocaml translates OCaml bytecode to JavaScript and is a well-liked, industrial-strength compiler for running OCaml on the web. The goal of Wasm_of_ocaml’s development is to retain the strengths of Js_of_ocaml and offer feature parity and inter-compatibility between the two compilers. You can compile your programs with Wasm_of_ocaml instead of Js_of_ocaml (you may have to make a few adjustments) and experience overall better performance.

Because of its popularity and versatility, creating an OCaml to Wasm translator has been a big priority for the team, and they continue to improve and optimise Wasm_of_ocaml over time.

What’s New?

Over the past year, much work has been done to get Wasm_of_ocaml to release readiness. Some of the changes include:

  • Putting Wasm_of_ocaml into the same development repo as Js_of_ocaml: This was a natural step due to how much code the two tools share, considering Wasm_of_ocaml is a fork of Js_of_ocaml. However, the two have diverged since the former was forked away from Js_of_ocaml. To put them in the same repo required changes to bring them back in sync. This change was necessary for the first public release of Wasm_of_ocaml. These are just a subset of all the fixes and contributions, and you can check out the work in the associated PR for a more complete picture.
  • Support for Wasm_of_ocaml in Dune: An important milestone on the road to the public release, this change allowed users to compile Wasm in Dune, making it much easier for existing OCaml projects to adopt the new tool. Wasm_of_ocaml support has been released in Dune 3.17.0, which you can upgrade to if you haven’t already.
  • Separate compilation: Support for separate compilation enables much faster compilation when building a program. There are two PRs: the first PR brings the main update, and the second PR makes it more fine-grained and avoids having to load too many modules.
  • Sourcemap support: PR #27 introduces support for source-level debugging of Wasm executables, implementing mapping between source and Wasm locations.
  • Support the JS String Builtins Extension: PR #33 change enables the use of JS string builtins when available for JS engines, which allows for more efficient operations on strings.
  • Minimise the use of the unsafe JS command eval: The JS command eval is known for being unsafe, and PR #24 creates an alternative workflow that minimises its use. Instead of using eval, strings can be emitted as external JavaScript fragments whenever the value of the string is known at compile time.
  • Store long-lived top-level values into global variables: PR #30 introduces a change where any variable that is used a number of instructions after being defined is stored as a global variable rather than a local variable. This change improves performance and reduces the compilation time of Wasm projects.
  • Updates to make Wasm_of_ocaml compatible with OCaml 5.2 and 5.3: Two PRs, #54 and #59, brought changes that made Wasm_of_ocaml compatible with OCaml: 5.2. For 5.3, PR #136 included updates to make Wasm_of_ocaml compatible with the then latest OCaml update.
  • Bugfixes: Let’s round off with some bug fixes! PR #22 ensured that locals are always explicitly initialised before being used, PR #31 fixed the spec-compliance of some emitted tuple instructions, and PR #46 fixed a stack resizing bug in structural value comparison.

Benchmarks and Performance

The team has run several benchmarks with exciting results. When comparing the performance of Wasm_of_ocaml to Js_of_ocaml and the native code of OCaml’s compiler ocamlopt, the results consistently show that programs compiled with Wasm_of_ocaml are faster than ones compiled with Js_of_ocaml (but two times slower than native code). This holds true not only for microbenchmarks but on macroscopic benchmarks as well. Even more impressively, Jane Street reports that they have observed 2x-8x performance improvements using Wasm_of_ocaml compared to Js_of_ocaml.

Another aspect of performance lies in casts and bound checks. Wasm_of_ocaml uses a generic representation of values, which means that, at run time, a number of casts might be required to ensure safety. Furthermore, due to the nature of the data representation the team has chosen, a bound check is required whenever a field of value is accessed. The team found that the Wasm_of_ocaml checks take up around 10% of the execution overtime on the V8 engine and 20% on the Bonsai benchmark. The goal is to keep improving performance by reducing the amount of needless casts.

Regarding file size, Wasm_of_ocaml output code takes up more space than Js_of_ocaml, which is likely due to Wasm being a lower-level language than JavaScript. For example, Wasm_of_ocaml has to generate explicit code to allocate closures and access the environment, both implicit in JavaScript.

If you’re curious to learn more about Wasm_of_ocaml’s benchmarks and performance, Jérôme Vouillon’s talk from the ML track at ICFP 2024 goes more in-depth.

Release process, Plus a New Version of js_of_ocaml

From now on, wasm_of_ocaml and js_of_ocaml will be released jointly. For this reason, this first public release of wasm_of_ocaml is numbered 6.0.1 since it is synchronised with the release of js_of_ocaml 6.0.1.

A new and important feature of js_of_ocaml 6.0.0 is double translation, a way of making programs that use effect handlers faster. Effect handler support is realised by compiling some functions to Javascript code in continuation passing-style (CPS), which incurs a performance penalty. By passing --effects=double-translation, some functions are compiled in several versions, and the choice of which version of the function to run is made at run time. This improves performance at the cost of slightly larger Javascript bundles. More details are available on the effect handlers page of the js_of_ocaml manual.

Until Next Time

If you want to try Wasm_of_ocaml yourself, start by checking out the documentation for it in Dune and in the manual. If you and have any feedback or questions, the best way to get in touch is on Discuss or in the repo for Js_of_ocaml and Wasm_of_ocaml.

Connect with Tarides online on Bluesky, X, Mastodon, Threads, and LinkedIn or sign up for our mailing list to stay updated on our latest projects.

Open-Source Development

Tarides champions open-source development. We create and maintain key features of the OCaml language in collaboration with the OCaml community. To learn more about how you can support our open-source work, discover our page on GitHub.

Explore Commercial Opportunities

We are always happy to discuss commercial opportunities around OCaml. We provide core services, including training, tailor-made tools, and secure solutions. Tarides can help your teams realise their vision