Tech News
← Back to articles

My fast zero-allocation webserver using OxCaml

read original related products more articles

Since helping with the OxCaml tutorial last year at ICFP, I've been chomping at the bit to use it for real in our research infrastructure for planetary computing to manage the petabytes of TESSERA embeddings we've been generating.

The reason for my eagerness is that OxCaml has a number of language extensions that give giant leaps in performance for systems-oriented programs, while retaining the familiar OCaml functional style of programming. And unlike Rust, there's a garbage collector available for 'normal' code. I am also deeply sick and tired of maintaining large Python scripts recently, and crave the modularity and type safety of OCaml.

The traditional way I learn a new technology is by replacing my website infrastructure with the latest hotness. I switched my live site over to building with OxCaml last year, but never got around to deeply integrating the new extensions. Therefore, what I'll talk about next is a new webserver I've been building called httpz which goes all in on performance in OCaml!

(Many thanks to Chris Casinghino , Max Slater , Richard Eisenberg , Yaron Minsky , Mark Shinwell , David Allsopp and the rest of the Jane Street tools and compilers team for answering many questions while I got started on all this!)

Why Zero Allocation for HTTP/1.1?

httpz is a high-performance HTTP/1.1 parser that aims to have no major heap allocation, and very minimal minor heap allocation, by using OxCaml's unboxed types and local allocations.

Why is this useful? It means that the entire lifetime of an HTTP connection can be handled in the callstack alone, so freeing up a connection is just a matter of returning from the function that handles it. In the steady state, a webserver would have almost no garbage collector activity. When combined with direct style effects , it can also be written without looking like callback soup!

I decided to specialise this library for HTTP/1.1 for now, and so settled on the input being a simple 32KB bytes value. This represents an HTTP request with the header portion (HTTP body handling is relatively straightforward for POST requests, and not covered in this post).

Given an input buffer like this, what can we do with OxCaml vs vanilla OCaml to make this go fast?

Unboxed Types and Records

... continue reading