At this point, Scheme is my favourite language to program in. And my prefered implementation (…there are a lot) is GNU Guile. I've written a couple of pieces of software using it: Bindings for termios on POSIX Systems, An implementation of Linear Feedback Shift Registers, A unit test framework that emits TAP output, A system that produces time-sheets from Redmine Timing exports, An elaborate system to describe and experiment with configurable electronic parts and native implementation of the XMMS2 protocol and client library. That latter I've written about before.

Now with Guile there's a lot going on. The project as a small but dedicated team of developers. And they have been working on improving the system performance by a lot. For the longest time, Guile only had an interpreter. The last version of that was 1.8 — the version I came in contact with for the first time as well. Shortly after I started to dabble, 2.0 was released so I didn't have a lot of exposure to 1.8. Version 2.0 added a stack VM that Guile byte-compiled its code to. In 2017 the project released version 2.2, which saw the stack VM replaced by a register VM. And that improved performance dramatically. And now, they are preparing a 3.0 release (2.9.1 beta release happened on October the 10th of this year), which adds just-in-time native code generation on x86-64 via GNU Lightning.

I used xmms2-guile to get an idea about the improvements that the different Guile versions offer. I couldn't be arsed to build myself a 1.8 release so, this won't look at that. The setup is a minimal client connecting to an XMMS2 server, pull out the information required to display a playlist of about 15300 tracks. All of this is running on an Intel Core i7 with plenty of memory, running XMMS2 version 0.8 DrO_o (git commit: 3bd868a9).

As a point of comparison, I ran XMMS2's command line client to do the same task. It took a mean time of 10.77 seconds. That's about 1420 tracks processed per second. I'm pretty sure the client does a little more than it needs to, but this establishes a ballpark.

With Guile 2.0 the whole affair takes 23.9 seconds. That's about 640 tracks per second. Quite a bit slower. More than twice as slow. I was sure this would be slower than the official client, but the difference is disappointing. So what about 2.2 — can it do better?

Well, in Guile 2.2 the same job takes 6.38 seconds. 2400 tracks per second! Impressive. This is why I think the official CLI client implemented in C does a little too much work than it needs. It shouldn't lose to this, and if it would, it shouldn't be behind this much. My xmms2-guile client library is a native implementation. It doesn't wrap the official XMMS2 client library that's written in C. I'm way too lazy to do detailed timing analyses of the different libraries and Scheme implementations. The results are reproducible, though.

Now what about the upcoming Guile 3.0? I've used 2.9.1.3-1f678 to be precise. It should execute a little faster, but the 2.2 results are pretty good already. Running the same setup yields a mean time of 5.87 seconds. A bit over 2600 tracks per second.

I mean sure, this is not an in-depth analysis, there's a local network connection involved and it's a rather specific repetitive task. Still though. Pretty cool when a random test shows that 3.0 is four times as fast as 2.0. ;)

Posted Tue 13 Nov 2018 00:55:34 CET Tags: