# Jane Street and Docker on moving to OCaml 5 at ICFP/SPLASH 2025

*2025-10-07 — note*


This is part 3 of 5 of a [series](https://anil.recoil.org/notes/icfp25) of posts[^4] about ICFP 2025.

It's been about six years since we wrote the papers on [parallelism](https://anil.recoil.org/papers/2020-icfp-retropar) and [effects](https://anil.recoil.org/papers/2021-pldi-retroeff),
and four years since we helped to [release](https://anil.recoil.org/notes/recapping-ocaml-22)
upstream OCaml 5.0 with multicore support, a [mammoth
effort](https://tarides.com/blog/2023-03-02-the-journey-to-ocaml-multicore-bringing-big-ideas-to-life/)
that took up years of work for my [OCaml Labs](https://anil.recoil.org/projects/ocamllabs) and
[Tarides](https://tarides.com) crew. After the release came out, I focussed on
building applications using OCaml 5 for my own work on [planetary computing](https://anil.recoil.org/projects/plancomp), for example on _using_ the new features with the
fledgling [Eio library](https://anil.recoil.org/papers/2023-ocaml-eio) to get some experience with
direct-style OCaml programming.

Meanwhile, big OCaml users have also been adapting their codebases to shift
from OCaml 4 to 5. Jane Street have expanded their tools and compiler team and
driven through their [production switch](#the-path-to-ocaml-5-in-production-at-jane-street) to the multicore runtime, and Docker for
Desktop is progressing with [their switch](#functional-networking-at-docker) to direct-style code via Eio for
hundreds of millions of users! Read on to learn more...


## The Path to OCaml 5 in Production at Jane Street

Although it was the last talk of the entire conference week, I'm discussing
this first as it was the most exciting thing I learnt at ICFP!  At the
[REBASE](https://conf.researchr.org/home/icfp-splash-2025/rebase-2025) [^1] workshop,
[Yaron Minsky](https://github.com/yminsky) [announced](https://www.youtube.com/live/UI1wApT2t1w?t=20700s) that Jane Street's production servers are now running
on the OCaml 5 runtime\!

<a href="https://www.youtube.com/live/UI1wApT2t1w?t=20700s"> <figure class="image-center"><img src="/images/icfp-29.webp" alt="Yaron Minsky showing the timeline of Jane Street's recent OCaml usage" title="Yaron Minsky showing the timeline of Jane Street's recent OCaml usage" loading="lazy" srcset="/images/icfp-29.768.webp 768w, /images/icfp-29.640.webp 640w, /images/icfp-29.480.webp 480w, /images/icfp-29.3840.webp 3840w, /images/icfp-29.320.webp 320w, /images/icfp-29.2560.webp 2560w, /images/icfp-29.1920.webp 1920w, /images/icfp-29.1600.webp 1600w, /images/icfp-29.1440.webp 1440w, /images/icfp-29.1280.webp 1280w, /images/icfp-29.1024.webp 1024w"><figcaption>Yaron Minsky showing the timeline of Jane Street's recent OCaml usage</figcaption></figure> </a>

That was the good news (our runtime is trading trillions of dollars, wow). The
bad news is that there was a bumpy road internally for Jane Street to go from
the version that was first released (OCaml 5.0 on [Dec
2022](https://ocaml.org/releases)) to their current tree.  Ron gave a really
good roundup of some of the effort that went into release engineering their
internal rollout. Since the entire OCaml runtime was
[rewritten](https://github.com/ocaml/ocaml/pull/10831) as part of the multicore
runtime upgrade, Jane Street encountered [GC pacing
issues](https://github.com/ocaml/ocaml/pulls?q=is%3Apr+pacing+label%3APerformance+is%3Aclosed)
and other unexpected changes in resource usage as a result of the new runtime
behaviours.  This took some significant design and engineering effort and to fix, which Ron
covers in detail in [his talk](https://www.youtube.com/live/UI1wApT2t1w?t=20700s).

### Diagnosing the OCaml 5 performance bumps

So what was the root cause of this bumpiness? I think a lot of it was just
normal release engineering; we clearly
[signalled](https://discuss.ocaml.org/t/ocaml-5-0-first-normal-alpha-release/10216)
when releasing OCaml 5.0 that it was not yet feature complete, and that the
4.x runtime would continue to be supported for some years.

> The developer team released OCaml 5.0.0 in December 2022. OCaml 5.x features
> a full rewrite of its runtime system for shared-memory parallel programming
> using domains and native support for concurrent programming using effect
> handlers.
> 
> Owing to the large number of changes, especially to the garbage collector,
> OCaml 4.14 (the final release in the OCaml 4.x series, originally released in
> March 2022) remains supported for the time being. Maintainers of existing
> codebases are strongly encouraged to evaluate OCaml 5.x and to report any
> performance degradations on our issue tracker.
> <cite>\-- [ocaml/ocaml README](https://github.com/ocaml/ocaml/blob/85cd5fd3dc0c1763926378a571ef215ce9512908/README.adoc)</cite>

The latest OCaml 5.4.0 release that came out just a [couple of
weeks](https://discuss.ocaml.org/t/ocaml-5-4-0-released/17365) ago is the first
release with full feature parity with the OCaml 4.x LTS branch. Features such
as [statmemprof](https://tarides.com/blog/2025-03-06-feature-parity-series-statmemprof-returns/),
the [MSVC port](https://tarides.com/blog/2025-01-15-using-clang-cl-with-ocaml-5/), [GC compaction](https://tarides.com/blog/2024-09-11-feature-parity-series-compaction-is-back/), [thread sanitizer](https://tarides.com/blog/2024-08-21-how-tsan-makes-ocaml-better-data-races-caught-and-fixed/), [RISC-V](https://github.com/ocaml/ocaml/pull/11418) and
[S390X](https://github.com/ocaml/ocaml/pull/11712) architecture support all had to be engineered back in. OCaml development
in recent years has been very developer intensive because of the need to not only
reintroduce these features, and _also_ keep up with the torrent of new features being introduced to OCaml 5.x.
All in all, I think it's been a very successful few years for the language to have kept steadily improving\!

### Should we maintain multiple language runtimes in OCaml?

However, Ron's talk was an excellent chance for us to reflect on what we might
have done differently with the benefit of hindsight. [David Allsopp](https://www.dra27.uk) posits that we should
have maintained the OCaml 4 and 5 runtimes simultaneously:

> One of the early ideas was to merge just the runtime changes as a separate
> runtime, leaving all the language changes to a subsequent update.  The main
> thing here would have been to upstream the immense changes to the allocator
> and garbage collector along with the domains and fibers machinery, while not
> yet exposing it.
> 
> I remember the concern being that having essentially a runtime variant (not
> unlike the debug runtime) might lead to very slow uptake at actually testing
> it and possibly a maintenance burden.  i.e. we were concerned at maintaining
> two runtimes. This would probably have resulted in something like OCaml
> 4.15.0, with an experimental official multicore-aware runtime.
> <cite>\-- [Reflections on ICFP 2025](https://www.dra27.uk/blog/platform/2025/10/18/icfp-2025.html), David Allsopp</cite>

I agree with this. Although we weren't sure in 2021 that it would be possible
to have two simultaneous runtimes[^2] it was clear by the time we were
engineering the 5.0 PR that this would be possible. Still, a few years to stabilise
multicore performance _vs_ the decade-old 4.x runtime isn't bad going at all, so I don't have
deep regrets about the approach we did take\!

### We need continuous continuous performance engineering

The other area where all of us agreed more effort is necessary is on continuous performance engineering.
In the runup to 2022, [Tom Kelly](https://github.com/ctk21), [KC Sivaramakrishnan](https://kcsrk.info) and I set up [Sandmark](https://github.com/ocaml-bench/sandmark), which
was a body of microbenchmarks and some macrobenchmarks. Tarides setup a [continuous benchmarking service](https://discuss.ocaml.org/t/ann-sandmark-nightly-benchmarking-as-a-service/10174) around this, and I hosted a bunch of [carefully tuned machines](https://github.com/ocaml-bench/ocaml_bench_scripts#notes-on-hardware-and-os-settings-for-linux-benchmarking) with specific BIOS settings in the Cambrige Computer Lab.

Roll on six years, and the maintainence cost of this service becomes clear.
It's quite a bit of effort to maintain the old machines (one is running Ubuntu
16.04! I'm not telling you which one) to keep consistency in previous results.
New machines all come with a proportional configuration effort, and their results
have to be interpreted. Operating systems have to be upgraded, and tuned afresh.
Continuous benchmarking is itself a continuous process of engineering, and should be treated as such\!

Our discussions at ICFP centred around the idea that we should not only maintain this
benchmarking infrastructure, but add an incentive to _macro_ projects to submit
representative tests of their performance. Rocq, Why3,
[Semgrep](https://semgrep.dev/blog/2025/upgrading-semgrep-from-ocaml-4-to-ocaml-5/),
or Frama-C, for example, should all have test cases run within this
infrastructure that move beyond microbenchmarks to realistic performance
patterns that will show up issues with GC pacing in a way that microbenchmarks
do not.

The challenge with doing this so far has been the difficulty of getting many of these
big projects to compile on a random OCaml trunk snapshot (essential to test them against
a pre-release OCaml compiler). Solving this will take some thought (particularly around
ppx usage), but the effort seems worthwhile as we move into a new phase of OCaml 5
engineering now that feature parity has been achieved. Stay tuned for more on this from
Tarides\!

## Functional Networking at Docker

I also had the opportunity to share both a retrospective on the work [Dave Scott](https://dave.recoil.org)
and I have been doing on [Docker Desktop](https://www.docker.com/products/docker-desktop/) for some years, and
_also_ the efforts from new OCamlers like [Patrick Ferris](https://patrick.sirref.org) and [Ryan Gibb](https://ryan.freumh.org) on helping us
to port some aging OCaml code over to OCaml 5.

We got a paper accepted to ICFP on the topic, and so I had a lot of fun
[presenting](https://www.youtube.com/watch?v=j84ocjlj1JA&t=12880s)
"[Functional Networking for Millions of Docker Desktops](https://anil.recoil.org/papers/2025-docker-icfp)" to the mainline ICFP audience!  I first discussed the
past; how we [joined Docker](https://anil.recoil.org/notes/docker-buys-unikernel-systems) and came up with [HyperKit and
VPNKit](https://www.docker.com/blog/docker-unikernels-open-source/) to solve
scaling problems that Docker was facing early in its growth.

<a href="https://www.youtube.com/watch?v=j84ocjlj1JA&t=12880s"> <figure class="image-center"><img src="/images/icfp-37.webp" alt="Me on stage at ICFP in a verrrry cold venue" title="Me on stage at ICFP in a verrrry cold venue" loading="lazy" srcset="/images/icfp-37.768.webp 768w, /images/icfp-37.640.webp 640w, /images/icfp-37.480.webp 480w, /images/icfp-37.320.webp 320w, /images/icfp-37.1920.webp 1920w, /images/icfp-37.1600.webp 1600w, /images/icfp-37.1440.webp 1440w, /images/icfp-37.1280.webp 1280w, /images/icfp-37.1024.webp 1024w"><figcaption>Me on stage at ICFP in a verrrry cold venue</figcaption></figure> </a>

Our experience report makes the broad case for library operating sytems and
functional programming being a good fit, especially with strict languages like
OCaml which offer thin interfaces to the OS interfaces.

> Our use of library-oriented programming to deliver Docker for Desktop is \[...\] a very
> useful way to build the "invisible systems glue" code that is pervasively needed in many systems
> programming tasks.
> 
> There are an ever-growing number of hardware and software interfaces to
> access the outside world, most obviously with GPUs for machine learning workloads but also
> FPGAs and new storage and persistent memory devices. These usually require significant
> retrofitting to work with existing codebases, and so building translation adapters like VPNkit and
> using library VMMs like Hyperkit will become more common in the future.
> <cite>\-- [Functional Networking for Millions of Docker Desktops](https://doi.org/10.1145/3747525), 2025</cite>

And looking into recent specifics, [Patrick Ferris](https://patrick.sirref.org)'s [contributions](https://github.com/moby/vpnkit/pull/646) to VPNKit also allow
this codebase to move to OCaml 5, and take advantage of direct-style IO! In a nutshell, it lets
old code like this:

```ocaml
module Make_packet_proxy
(I: Mirage_flow.S) (O: Mirage_flow.S) = struct
 let run incoming outgoing =
  let rec loop () =
   I.read incoming >>= function
   | Error err -> fail "%a" I.pp_error err
   | Ok `Eof -> Lwt.return_unit
   | Ok (`Data buf) -> begin
      O.write outgoing buf >>= function
      | Ok () -> loop ()
      | Error err -> fail "%a" O.pp_error err
     end
  in loop ()
```

...migrate to direct-style code Eio like this:

```
module Proxy = struct
 let run incoming outgoing =
  try
    while true do
      Eio.Flow.copy incoming outgoing
    done
  with
  | End_of_file -> ()
  | Write_error err ->
      fail "%a" pp_write_error err
  | Read_error err ->
      fail "%a" pp_read_error err
end
```

The old code[^3] had monadic concurrency, functors for parameterising the IO
drivers, and error handling duplicated across OCaml exceptions and the
concurrency monad. The new code uses direct control flow constructs like
`while`, and also one form of error handling.  This is all still a
work-in-progress, but looking a solid approach with no blockers except hacking
time to get it merged.

Read the [ICFP paper](https://doi.org/10.1145/3747525) to learn more about
this, or [browse my slides](/slides/icfp-docker-25.pdf)!  It's exciting to see
production code here get simpler _and_ faster as we move to OCaml 5.  The reasons
why this happens are explored further in my [VMIL keynote talk](https://anil.recoil.org/notes/icfp25-post-posix)
that I gave the next day, where I make a case for runtimes focussing on
post-POSIX IO! And beyond that, we have [OxCaml waiting in the wings](https://anil.recoil.org/notes/icfp25-oxcaml)
for even more performance gains. OCaml is living in exciting times.

[^1]: As far as I can tell, REBASE is SPLASH's equivalent of the
 venerable [CUFP](http://cufp.org/) series that I helped run earlier in the
 century.

[^2]: Our 2020 [parallelism paper](https://anil.recoil.org/papers/2020-icfp-retropar) proposed _two_ minor GC
 strategies, one of which broke the C FFI and so didn't make the cut in the end
 due to the amount of ecosystem churn it would cause.

[^3]: A fun historical note is that I gave one of the [first talks](https://anil.recoil.org/videos/dbd7546a-95d8-40af-b286-3cf930767682) about VPNKit in Jane Street London about a decade ago! Back then we had a deep discussion about whether to use Lwt or Async, and it looks like we'll now meet again via [OxCaml](https://anil.recoil.org/notes/icfp25-oxcaml).

[^4]: See also in the [ICFP25](https://anil.recoil.org/notes/icfp25) series: [chairing PROPL25](https://anil.recoil.org/notes/icfp25-propl), the [OxCaml tutorial](https://anil.recoil.org/notes/icfp25-oxcaml), [multicore at Jane Street and Docker](https://anil.recoil.org/notes/icfp25-ocaml5-js-docker), [post-POSIX IO](https://anil.recoil.org/notes/icfp25-post-posix) and [what I learnt](https://anil.recoil.org/notes/icfp25-what-i-learnt).
Synopsis: Jane Street's production deployment of OCaml 5 and Docker's migration to direct-style programming with Eio presented at ICFP.
Words: 1839
DOI: 10.59350/3jkaq-d3398

## Related

- [Self-hosting email the hard way from your own routable IPv4 block up](https://anil.recoil.org/notes/recoil-self-hosting-2026) (note, 2026-06-06)
- [AoAH Day 5: Bytesrw Eio adapters and automating opam metadata](https://anil.recoil.org/notes/aoah-2025-5) (note, 2025-12-05)
- [ICFP 2025](https://patrick.sirref.org/icfp-2025/) (feed, 2025-10-24)
- [A Roundup of ICFP/SPLASH 2025 happenings](https://anil.recoil.org/notes/icfp25) (note, 2025-10-10)
- [What I learnt at ICFP/SPLASH 2025 about OCaml, Hazel and FP](https://anil.recoil.org/notes/icfp25-what-i-learnt) (note, 2025-10-09)
- [It's time to go post-POSIX at ICFP/SPLASH 2025](https://anil.recoil.org/notes/icfp25-post-posix) (note, 2025-10-08)
- [Jane Street and Docker on moving to OCaml 5 at ICFP/SPLASH 2025](https://anil.recoil.org/notes/icfp25-ocaml5-js-docker) (note, 2025-10-07)
- [Holding an OxCaml tutorial at ICFP/SPLASH 2025](https://anil.recoil.org/notes/icfp25-oxcaml) (note, 2025-10-06)
- [Programming for the Planet at ICFP/SPLASH 2025](https://anil.recoil.org/notes/icfp25-propl) (note, 2025-10-05)
- [Functional Networking for Millions of Docker Desktops](https://anil.recoil.org/papers/2025-docker-icfp) (paper, 2025-08-01)
- [OxCaml Labs](https://anil.recoil.org/projects/oxcaml) (project, 2025-01-01)
- [Eio 1.0 – Effects-based IO for OCaml 5](https://anil.recoil.org/papers/2023-ocaml-eio) (paper, 2023-09-01)
- [OCaml.org: recapping 2022 and queries on the Fediverse](https://anil.recoil.org/notes/recapping-ocaml-22) (note, 2023-01-02)
- [Planetary Computing](https://anil.recoil.org/projects/plancomp) (project, 2022-01-01)
- [Retrofitting effect handlers onto OCaml](https://anil.recoil.org/papers/2021-pldi-retroeff) (paper, 2021-06-01)
- [Retrofitting parallelism onto OCaml](https://anil.recoil.org/papers/2020-icfp-retropar) (paper, 2020-08-01)
- [The functional innards of Docker for Mac and Windows](https://anil.recoil.org/videos/dbd7546a-95d8-40af-b286-3cf930767682) (video, 2016-06-24)
- [Unikernel Systems acquired by Docker](https://anil.recoil.org/notes/docker-buys-unikernel-systems) (note, 2016-01-21)
- [OCaml Labs](https://anil.recoil.org/projects/ocamllabs) (project, 2012-01-01)

---
Canonical: https://anil.recoil.org/notes/icfp25-ocaml5-js-docker
Type: note
License: CC BY 4.0 <https://creativecommons.org/licenses/by/4.0/>
Tags: oxcaml, ocaml, programming, docker, multicore, icfp
