37 percent of HyperRogue’s compilation time is due to std::function

HyperRogue, the most mind-expanding roguelike in existence, is written in C++11 and uses a “unity build” model — every source file is #included into a single translation unit and compiled all in one go. That single compiler invocation takes about 142 seconds on my MacBook.

Yesterday I replaced all of the std::functions in HyperRogue with a hand-rolled minimalistic hyper_function. This new version compiles in about 90 seconds!

By replacing std::function, we eliminate 37 percent of the compile time; 23 percent of the linker symbols; 8.3 percent of the size of our object file; and 7.5 percent of the size of our final executable. (These specific numbers are of course unique to HyperRogue, which uses a lot of first-class functions and thus benefits a lot from replacing std::function. Your benefits may vary.)

My somewhat self-serving conclusion: It’s really important to keep teaching people how to do type erasure! If you’ve been taught well, so that you’re comfortable whipping up a type-erased wrapper in 60 lines of code, you can get some pretty nice improvements over the stuff that ships in the standard library.


Incidentally, today I learned that std::function<void()> does not complain about being assigned a value-returning function:

std::function<void()> f = []() { return false; };  // oops, void function shouldn't return anything

Replacing std::function with my hand-rolled version turned up a lot of nitpicky little bugs like this in the HyperRogue code, which was another neat benefit of the change.

Posted 2019-01-06