Tutorial: How to Port Lwt Applications to Eio

by Isabella Leandersson on Sep 27th, 2023

Thomas Leonard and Jonathan Ludlam hosted a tutorial on porting Lwt applications to OCaml 5 and Eio at arguably the world's largest functional programming conference: ICFP. The tutorial is a great introduction to Eio, with a clear step-by-step approach that is accessible to developers of different experience levels.

This article provides some context to the tutorial and Eio in general. If you would rather skip straight to the code, check out the tutorial on GitHub.

Eio: a Brief Introduction

OCaml 5 brought support for programming with effects. Using effects has several advantages over using call-backs or monadic style:

  1. It is faster – no heap allocations are required to simulate a stack.
  2. Concurrent and plain non-concurrent code can be written in the same style.
  3. Exception backtraces work.
  4. Other language features such as try/with, match, while etc can be used with concurrent code.

The OCaml 5 update also brought Multicore support, which has big implications for better performance across a multitude of use cases.

In light of these changes, there was a lot of interest in moving existing OCaml code to a new I/O library that could make the best use of both effects and multiple cores. With this impetus, a new effects-based direct-style I/O stack was developed for OCaml – enter Eio.

Why Eio?

Beyond Multicore and effects support, Eio comes with several useful features such as making use of lock-free data structures (see Saturn, modular programming support, interactive monitoring support enabled by the custom runtimes in OCaml 5.1, and interoperability with other concurrency libraries such as Lwt, Async, and Domainslib.

Eio and Lwt

When comparing Lwt and Eio there are a few things to consider. First of all, Eio's use of direct-style is shorter and easier for beginners to use. Secondly, and perhaps more significant to the average user, Eio is faster. This holds true even when just one core is being used. For a more detailed breakdown of times, check out the Eio Introduction and Lwt Comparison part of the tutorial.

Eio also manages error handling and backtraces differently; for example, Eio reports exceptions immediately in cases where two tasks are running concurrently, and backtraces are also more specific. Furthermore, Eio prevents the type of resource leaks that Lwt often allows to happen by requiring all resources to be tied to a switch, ensuring that they are released when the switch finishes.

Finally, Eio makes it clearer to understand how the program relates to the outside world since it does so through a function argument usually named env. By looking at what happens to env, the user gets a bound on the program's behaviour. Lwt does not do this, typically just starting by saying it will run main with no further context.

Tutorial Overview:

The tutorial covers the following topics:

  • Prerequisites: Walks you through what to install before starting the tutorial, including optional Docker and ThreadSanitizer files, as well as tips and common pitfalls.
  • Eio Introduction and Lwt Comparison: Outlines the main differences between Eio and Lwt, including performance, error handling, and bounds on behaviour.
  • Porting From Lwt to Eio: The core of the tutorial, this section walks you through how to take an example application in Lwt and port it to Eio. It gives you an overview of the code, tells you how to convert the code, and how to take advantage of Eio features.
  • Using Multiple Cores: Instructions on how to use multiple cores to improve performance. The section includes topics like thread-safe logging, using multiple domains with cohttp, testing, and suggestions on useful tools.

Feedback

It really helps the teams to receive feedback and constructive comments on how to improve documentation for users. We encourage you to share your thoughts on the repo, or on the OCaml Discuss forum.

You can also contact us on our website with any questions or concerns.