Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.


how to prevent code bloat with loki visitor

  • Richard Ulrich
    Richard Ulrich

    We are in the process of switching from a c-style-type-switch to loki::visitor.
    Our class hierarchy has 54 classes at the moment.
    I have them grouped like this:

    typedef LOKI_TYPELIST_7
    ) TlObGlStructure;
    typedef LOKI_TYPELIST_5
    ) TlObGl3dVolumes;
    typedef Loki::TL::Append<TlObGlStructure, TlObGl3dVolumes>::Result TlObGlEntityClasses;

    It works well, and compared to the former approach, is a pleasure to work with.

    But recently I discovered, that the linker almost uses up all the available RAM.
    By looking closer, I discovered that some obj files increased the size tenfold e.g.  form 2MB to 20MB.
    Analyzing with dumpbin.exe I found that loki indeed contributes a good fraction of the symbols found in the obj.
    Especially the deeply nested typelists.

    Is there a way to prevent this bloat?

  • Richard Ulrich
    Richard Ulrich

    Solved it with the following actions:
    1)  instead of 
    typedef Loki::CyclicVisitor<void, TlObGlEntityClasses> ObGlVisitor;
    I'm using
    class __declspec(dllexport)  ObGlVisitor : public Loki::CyclicVisitor<void, TlObGlEntityClasses> { };
    which allows me to forward declare ObGlVisitor.

    2) Instead of using  the LOKI_DEFINE_CYCLIC_VISITABLE macro,  I have split the definition and implementation in the header and cpp files.

    3) Moved the definition of the concrete visitor into a separate header file, thus the client code that only uses the functionality only gets a few function definitions while only the files that are concerned with the implementation of the functionality get to know the visitor.

    4) Using explicit template instantiation declaration and -definition for ObGlVisitor as described at:

    The combined effect is that the summed size of the obj files is now below what it was before applying the visitor.

  • Thanks for posting that tip for others.  I like how C++ allows forward referencing to reduce the number of header files developers must include.  As you show here, forward referencing also reduces code-bloat when working with complex templated typedefs.



  • Richard Ulrich
    Richard Ulrich

    In the meantime we had to solve another problem.
    For fast dispatching, we use the cyclic visitor. And at dispatching it really is fast, but a co-worker discovered, that the visitor is slow in construction. The disassembly revealed that the constructor of the visitor builds a huge vtable for all the 54 incarnations of the recursive template. I would expect the compiler to be able to optimise these base classes away as they only contain a pure abstract function definition. But MSVC8 doesn't, others might?
    So I put the visitor into a singleton which can only be accessed by an accompanying RAII manager class. The manager class sets the member variables of the visitor, and makes sure only one caller uses the visitor singleton at a time. As our code is mainly single threaded, that's no problem. Otherwise it might be good to have one singleton instance per thread if it's a finite thread pool.
    After all, the whole mechanism is not as simple anymore as I would like it to be, but now it seems to perform well.


  • Alber Kami
    Alber Kami


    Wouldn't a cached factory will be just what you need ?
    Instead on creating the visitor on the stack\heap just create it with a Loki cached factory.
    this solution is very scalable for later MT and very easy to implement using Loki.