Breaking ABI

16 Mar 2008 • 3 min read

Well, since the initial OpenRC release, quite a few people where vocal on IRC bitching about it's use of reallocing a NULL terminated char** list with claims that it's slow and inefficient. So, I decided to take the test and rework OpenRC around the TAILQ macros as found in queue(3) for dealing with lists of strings - which it does a fair bit. After spending more time than I anticipated on this, here are the results on my slowest box measured by bash's time feature:


ubersparc ~ # time rc
real    0m0.215s
user    0m0.036s
sys     0m0.179s
ubersparc ~ # time /etc/init.d/local restart
 * Stopping local ...                                                                 [ok]
 * Starting local ...                                                                 [ok]

real    0m0.331s
user    0m0.086s
sys     0m0.251s


ubersparc ~ # time rc
real    0m0.204s
user    0m0.042s
sys     0m0.161s
ubersparc ~ # time /etc/init.d/local restart
 * Stopping local ...                                                                 [ok]
 * Starting local ...                                                                 [ok]

real    0m0.338s
user    0m0.082s
sys     0m0.262s

So we can see that rc itself is quite a bit faster than before, as it did the bulk of string processing. However, services themselves are slightly slower. Why is this? Well, to keep the code similar we have to malloc and return a list head even if the list is empty. valgrind shows this as well, rc has less mallocs, whereas the services have more. So to improve the code futher we need to stop blindly mallocing list heads. It's hard to time overall speed, and my sparc doesn't run bootchart so I'll see if I can make some on my laptop, but my gut feeling is that it's no faster or slower overall than before.

In other words, using linked lists is only beneficial when dealing with large quantities of data. OpenRC doesn't deal with large quantities of data and as such is slower for starting individual services. The main speedup is purely due to joining and sorting which is faster due to linked lists.

This code has now been committed to git and the ABI has been broken (obviously - duh). The only things that links to us at this time are splashutils and einit. Here's a patch to splashutils to make it work again. If I think it has no immediate benefit, why did I commit the code? Well, the answer is purely because it will scale a lot better so hosts with lots of services will see a better speed increase than my slow sparc with few services.

I've also re-factored the code to match the BSDs KNF coding style and ditched my own custom one. It was fairly similar, so its not much of a change - the benefit is that hopefully more people will enjoy it 😃