[RFC] Lazy facet instantiation in libc++ locale

Although it isn’t common for embedded applications to rely on C++ streams and locale, it does happen, and it appears that a lot of the code size introduced when locale is used can be traced back to facets. Facets encapsulate locale-dependent information. It looks like our implementation of locale.cpp (like GNU, from what I can tell) instantiates all facets on creation of the locale, even if a facet isn’t used during the runtime of the application.

Section 3.2.2 of the Technical Report on C++ Performance (https://www.open-std.org/jtc1/sc22/open/n3646.pdf) describes a different approach to this called lazy facet initialization in which use_facet() is modified to ensure that a facet is only created if it is referenced from the program (using templates), and this can drastically reduce the static size of a program that relies on locale. I ran a (very rough) simple experiment in which I removed unneeded facets from the locale with a test using streamstream (keeping ctype), and the static link contribution of locale.cpp dropped from 163K to just 3K.

It looks like this was proposed to GNU back in 2005 (tracked in 24881 – Lazy facet instantiation)

Has anyone attempted this in LLVM or does anyone have a plan to attempt this?

Alan Phipps
Texas Instruments

1 Like

I’ve also noticed this issue when statically linking libc++ into small binaries (“moneypunct”, seriously, who uses that?). I never really tried to look into a solution other than “Well, just don’t use streams, then.” If there’s a good way to solve this without throwing out iostreams, that sounds great!

I’d only worry that, given the same person (Howard Hinnant) initially wrote LLVM libc++ a few years after sending that proposal to the libstdc++ mailing list, there might be some reason why it turned out not to be feasible after-all. But, it’s always possible he just forgot or didn’t get around to it.

1 Like