Skip to content

Consider single instantiation for some templates #106

Open
@nyh

Description

@nyh

Templates are usually instantiated again and again for each source file. This is not only slow, but in extreme cases can also generate huge ".o" files, which contain duplicate copies of the exact same code, as well as debugging information for this code (which in C++, with its very long symbol names and deep type hierarchies, is notoriously large).

Probably the most extreme example is our debug() function, which uses various C++ templates to do its work. The 58-line core/power.cc compiles (with debugging information) to an 1.3 megabyte ".o" file, because of this. Huge object files take space, and also a lot of memory during the linking phase.

The solution is to specialize debug(), for some popular combinations of types, once in a single source file, and then in the debug.hh header file say that certain specializations are external (so don't need to be compiled again if used).

More concretely, we can add this to debug.cc:

// Instantiate once various forms of debug defined in debug.h, so that we
// don't need to do it separately for each source file.
template void debug(const char*, const char*);
template void debug(const char*, const char*, const char*);
template void debug(const char*);
template void debug(const char*, int);
template void debug(const char*, unsigned int);
template void debug(const char*, double);

And this in debug.hh:

// The code above, compiled separately for each source file, generates huge .o
// files (as an example, adding a debug("...", "...") call to power.cc
// added to its .o's size by over 1 megabyte, mostly debugging information).
// So instantiate some common use cases once, in debug.cc, and reuse them.
extern template void debug(const char*, const char*);
extern template void debug(const char*, const char*, const char*);
extern template void debug(const char*);
extern template void debug(const char*, int);
extern template void debug(const char*, unsigned int);
extern template void debug(const char*, double);

The size of power.o and many other objects using debug() is reduced 10-fold. The size of our loader.elf is reduced from 40MB to 38MB (I'm not sure why, the duplicate implementations should have all been eliminated). The loader-stripped.elf remains more-or-less the same.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions