Back in July, I used MirageOS to create my first unikernel, a simple REST service for queuing file uploads, deployable as a virtual machine. While a traditional VM would be a complete Linux system (kernel, init system, package manager, shell, etc), a Mirage unikernel is a single OCaml program which pulls in just the features (network driver, TCP stack, web server, etc) it needs as libraries. Now it's time to look at securing the system with HTTPS and access controls, ready for deployment.
Visualising an Asynchronous Monad
Many asynchronous programs make use of promises (also known as using light-weight threads or an asynchronous monad) to manage concurrency. I've been working on tools to collect trace data from such programs and visualise the results, to help with profiling and debugging.
The diagram below shows a trace from a Mirage unikernel reading data from disk in a loop. You should be able to pan around by dragging in the diagram, and zoom by using your mouse's scroll wheel. If you're on a mobile device then pinch-to-zoom should work if you follow the full-screen link, although it will probably be slow. If nothing else works, the ugly zoom buttons at the bottom zoom around the last point clicked.
Simplifying the Solver with Functors
After converting 0install to OCaml, I've been looking at using more of OCaml's features to further clean up the APIs. In this post, I describe how using OCaml functors has made 0install's dependency solver easier to understand and more flexible.
Optimising the Unikernel
After creating my REST queuing service as a Mirage unikernel, I reported that it could serve the data at 2.46 MB/s from my ARM CubieTruck dev board.
That's fast enough for my use (it's faster than my Internet connection), but I was curious why it was slower than the Linux guest, which serves files with nc
at 20 MB/s.
My First Unikernel
I wanted to make a simple REST service for queuing file uploads, deployable as a virtual machine. The traditional way to do this is to download a Linux cloud image, install the software inside it, and deploy that. Instead I decided to try a unikernel.
Unikernels promise some interesting benefits. The Ubuntu 14.04 amd64-disk1.img cloud image is 243 MB unconfigured, while the unikernel ended up at just 5.2 MB (running the queue service). Ubuntu runs a large amount of C code in security-critical places, while the unikernel is almost entirely type-safe OCaml. And besides, trying new things is fun.
Python to OCaml: Retrospective
In 2013, I spent 6 months converting 0install's 29,215 lines of Python to OCaml (learning OCaml along the way). In this post, I'll describe the approach I took and how it went. There will be graphs. If you don't want to read the whole thing, the take-away is this: The new code is a similar length (slightly shorter), runs around 10x faster, and is statically type checked.
OCaml: What You Gain
Way back in June, in Replacing Python: second round, I wrote:
The big surprise for me in these tests was how little you lose going from Python to OCaml.
Of course, I was mainly focused on making sure the things I needed were still available. With the port now complete (0install 2.6 has been released, and contains no Python code), here's a summary of the main things you gain.
OCaml: The Bugs So Far
OCaml's static typing allows it to detect many problems at compile-time. Still, some bugs slip though. In this post, I go over each discovered bug that made it into a Git commit and try to work out why it happened and whether it could have been prevented.
Polymorphism for Beginners
OCaml makes heavy use of parametric polymorphism (which you may also know as "generics" in other languages). The OCaml tutorials mention it from time to time, but the information is spread about over many articles and they don't go into much detail. I'm not a type theorist, just a Python/Java/C programmer who finds this stuff interesting. I wanted to write this guide while I still remember the things that confused me. I know several OCaml experts keep an eye on this blog, so hopefully any inaccuracies will be corrected in the comments.
Asynchronous Python vs OCaml
I've now migrated the asynchronous download logic in 0install from Python to OCaml + Lwt. This post records my experiences using Lwt, plus some comparisons with Python's coroutines. As usual, the examples will be based on the real-world case of 0install, rather than on idealised text-book examples.