Tip: speeding up s11n client compile times
September 2, 2008 on 12:57 pm | In libs11n |As i’ve written in the past few blog entries, as part of the QBoard project i’ve been working on s11n proxies for serializing a variety of Qt types. That application has helped stress a lesson which i actually learned a long time ago, but had forgotten what an impact it makes. It potentially affects all s11n clients, so i thought i’d share it…
Two days ago, QBoard needed about 70 seconds to compile using parallel compilation on a dual-processor machine. After refactoring the s11n support a bit (as explained below), it now takes about 40 seconds. The extra 30 seconds were due 100% to libs11n, and we’ll see why below…
Any user of libs11n is probably familiar with the registration of s11n proxies. In its simplest form it looks like this:
#include <s11n.net/s11n/proxy/pod/int.hpp>
That registers the “int” type as a first-class Serializable. More commonly, for client-side types a registration looks like:
#define S11N_TYPE QVariant #define S11N_TYPE_NAME "QVariant" #define S11N_SERIALIZE_FUNCTOR s11n::qt::QVariant_s11n #include <s11n.net/s11n/reg_s11n_traits.hpp>
That registers a proxy for QVariant.
That registration process does several things:
- Sets up a class template specialization for the client-specified type, such that calls to s11n::de/serialize(…,ThatType) will go through the appropriate API (in the above case, the QVariant_s11n functor).
- Sets up a classloader registration, so that deserializing of pointers can be done polymorphically. (That is actually the only reason in the world why libs11n has to associate a class name with types. For types which never get deserialized by pointer, this registration is never used!)
- There’s something else here which is slipping my mind at the moment.
In any case, the registration process is not (internally) 100% trivial, though the client has only to include a header file.
A registration must be visible to all client code which attempts to de/serialize that type, or else de/serialization will not work (that’s not true for some special cases, actually). This normally means including it in a common header file, and that’s where we hit our problem…
A registration creates several template specializations which the client will never see, but which nonetheless must be created by the compiler in order for s11n to do its work. That create happens in every client file which includes the registration, and can take a measurable amount of time per registered type (some experiments have shown a bit over 1 second per registered type!).
In the case of QBoard, we currently have registrations for almost 30 Qt types. Until a couple days ago, those registrations were all in a single header file which was included by all clients which wanted to de/serialize Qt types.
In the interest of a cleaner build tree, i split up the monolithic header into one header per serialized type, and then went back and updated the client code to only include the headers they needed. After doing so, the total build time was cut from about 70 seconds to about 40 seconds. The 30 extra seconds were taken up solely with the compilation of the s11n registration code.
So, the lesson is: try to give your s11n registrations the lowest visibility possible. Everywhere they are visible, they will be compiled, and where they are compiled they will take an observable amount of time to do so. In some cases it is possible to encapsulate all s11n-related calls into a small number of implementation files, invisible to the majority of the client code. The speed benefits of doing can be worth it. Consider, for example, if you save 30 seconds per build (as QBoard did), and it takes 30 minutes of work to refactor the registrations, then it will only take 60 compilation runs to win that time back. If you follow this lesson from the start, as opposed to refactoring later, you’ll get even more time benefits (because you obviously save the refactoring time).
Have fun, and happy hacking!
1 Comment »
RSS feed for comments on this post. TrackBack URI
Leave a comment
Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds.
Valid XHTML and CSS. ^Top^