This post is a long overdue homage to the wonderful work done recently by The Mono Project team.
The first thing I want to commend is the fact that installs have been made easier. Ironically, installing Mono on Linux used to be a bit more difficult than installing it on Windows, with the Mono site simply informing you what ancient version your distribution has in its official packages. Good luck waiting for an upgrade! I wanted a working, stable but up-to-date version, which involved finding the appropriate Ubuntu PPA myself… Now, the site gives instructions for adding an official PPA and they work wonderfully. It also upgraded MonoDevelop, and I’m really enjoying version 5 of the IDE. The new GUI put me off back when I tried it out for the first time. Now I feel it’s actually quite distraction-free, elegant and to the point.
So that’s wonderful. But the real reason for this post are the improvements to the performance of the Mono platform.
This is how the Shielded library performs when doing serial micro-transactions now:
cost of empty transaction = 0.180 us cost of the closure in InTransaction<T> = 0.025 us cost of the first read = 0.145 us cost of an additional read = 0.048 us cost of Modify after read = 0.765 us cost of Assign after read = 0.680 us cost of the first Modify = 0.800 us cost of an additional Modify = 0.045 us cost of a Value after Modify = 0.038 us cost of the first Assign = 0.840 us cost of an additional Assign = 0.041 us cost of the first commute = 1.470 us cost of an additional commute = 0.388 us
Small reminder: the purpose of the serial test is to roughly determine the overhead of STM in non-conflicting situations. The test runs a large number of transactions of various kinds, measuring their time, and based on the differences estimates the total cost (not method running time!) of using a certain operation in a transaction.
Now, it’s been some time since the last post on performance of Shielded, and the gains here do not just come from the Mono upgrade. The most notable improvement in the library itself is the new lock-free version tracking mechanism, which naturally unified both tracking of versions still being read and trimming of unnecessary old copies. Along with that, a custom hash set implementation (faster than the default HashSet<T> since Shielded does not need removal) and changing some foreach loops to for loops have also brought performance gains. (BTW, the test output above still mentions the method Assign, which does not exist for some time now. Shielded<T> now has a property Value with a getter and setter.)
But a lot of the difference is just due to Mono. I don’t have the old results just before the upgrade to let the difference speak for itself, but I can tell you I was blown away. After that upgrade, the performance on this test is now on par with its performance on the Microsoft .NET Framework. And actually – the Mono version is faster! I mean, it runs a million simple one-write transactions per second. I test it on an Ubuntu laptop, with an older i5 CPU, and compare it with a relatively new i7 machine running Win8, at a higher CPU frequency, and the difference is there. Win8/.NET is about 30% slower, despite the stronger CPU.
Not all tests are like this, though. The ConcurrentDictionary in Mono is still very slow compared to the MS.NET one, but apparently the Mono Project is now using the reference source of concurrent collections, and I presume the next version to come out will fix this, and perhaps beat MS.NET in all the tests.
A part of the reason for this win is probably in the Linux kernel. But none the less, the latest versions of Mono are impressive! With this platform now sporting a healthy generational garbage collector and performance like this, I think it deserves to be taken very seriously.
Kudos, Mono team!