Gabriel Poesia

Starting to contribute to Mozilla Servo

I've recently started contributing to Servo, a parallel browser engine being developed by Mozilla Research. It's written in Rust, an innovative and closely related systems programming language also from Mozilla.

A browser engine is the largest part of the browser. It receives HTML, CSS and JavaScript, and turns that into something your screen can display and you can interact with. Servo's goal is to be twice faster than existing browser engines by exploiting parallelism as much as possible, in parts that are currently sequential in Chrome, Firefox, Safari, Edge, etc. Significant parallelism is extremely hard to simply add to such large existing systems as an afterthought.

A faster browser not only means a better experience in a Web where insane innefficiency became the norm (after all, people are making browsers faster so Web developers shouldn't need to care, right?), but also a longer-lasting battery for our mobile devices. Given that we are probably reaching physical limits in battery manufacturing, the main way of extending battery power from now on may be making our software and hardware more efficient.

It's being a very nice experience. I've sent three Pull Requests up to now, and while none of them is extremely complex, you still get the feeling of doing something good (aside from learning a lot). Servo is being developed entirely on Github, which makes the involvement process fairly standard and simple.

Furthermore, for someone interested in Math and algorithms, Servo is also a technically interesting project. This is shown in several fronts. I have some examples that were particularly eye-catching to me, but interesting problems seem to show up in various parts.

First, the pipeline that gets from HTML+CSS to an image that you can see is pretty beautiful (a.k.a. an example of Good Design). This is also reflected in the code. My third PR fixed a bug related to collapsed borders in table rows not showing up, while border collapsing already worked for cells. After reading a lot of Wiki pages explaining architecture and algorithms, without having touched the code base before (which, as expected, is pretty large), I had a clear idea of what kind of thing to look for in more-or-less what module, which turned out to be right (also, some well-placed FIXMEs helped me understand the issue). This was a very pleasant surprise.

Another example is pcwalton's description of his implementation of CSS Box Shadows. It turns out that something that is as simple as a CSS property for the Web developer actually needs quite a bit of math to work on the browser side. Shadows are a Gaussian Filter, and Servo's implementation relies on some math tricks like approximating sums with integrals, one I've met through Concrete Mathematics. It's really nice to see things like this trick being actually used, albeit rarely.

Finally, Servo's layout algorithm basically consists of a series of alternating top-down and bottom-up parallel tree traversals, in a carefully chosen order. These parallel tree traversals are the heart of Servo. It's a nice heart for a project to have, isn't it?

As a last interesting point, Servo is written in, and closely related to the development of, the Rust programming language. Several languages appeared in the last years with the promise of eventually being a replacement for C++. To date, all of them failed, even if most still found their niches. But being as fast as C++ is still a requirement for many projects where performance cannot be sacrificed. Rust is the first language I see with a fundamentally different proposal for how to build a systems programming language. It is as fast as C++ because it also works with zero-cost abstractions, i.e. shiny features don't slow down your code, since they're equivalent to the uglier, fast low-level code you could write by hand. On the other hand, Rust has strong safety guarantees, something C++11's smart pointers can only dream of. For instance, if your Rust program compiles, it is guaranteed to have no data races (a subset of race conditions). In order to achieve that, Rust had to introduce new concepts, like lifetimes and borrows, which don't actually exist in other programming languages. It feels a bit like learning a new paradigm, since it requires you to think differently about resources and ownership. It's also harder to make your program compile in the beginning. Of course, as a result, you end up being more confident, to the extent possible, that your code works.

I'll write about other specially interesting things that I find on the way. My friend Victor joined me in this, and we were both mentioned in Servo's blog as new contributors (in weeks 71 and 73). A kind way to make you feel part of the community, even after very small contributions! Also, there was always Reuben keeping me updated and inspired by Mozilla projects.