Hi folks, this is related to topic Speed up #include (I can’t link, since I’m new) [EDIT Axel: added link], but I didn’t know the necro rules and I have more to ask so I started a new topic.
Overview
I’m using Cling to build jank, a Clojure dialect for C++ with JIT compilation. I have jank->C++ codegen and Cling JIT compilation working well, but I’ve run into a troublesome performance issue on startup. My startup code for Cling looks like this:
auto const jank_location(jank::util::process_location().unwrap().parent_path());
auto const args(jank::util::make_array("clang++", "-std=c++17"));
interpreter = std::make_unique<cling::Interpreter>(args.size(), args.data(), LLVMDIR);
interpreter->AddIncludePath(jank_location.string() + "/../include");
interpreter->AddIncludePath(jank_location.string() + "/../include/cpp");
/* This takes 1.4 seconds on my very nice desktop. */
interpreter->loadHeader("jank/prelude.hpp");
The issue, as the code shows, is that starting up any jank program with the JIT enabled sets the floor of the boot time to be 1.4 seconds, which is much higher than my use cases can tolerate.
Solutions
The topic I linked above included a few suggestions to address this, namely:
- Modules (not yet supported, based on the link above)
- PCHs (not yet supported, based on the link above)
- Autoloading maps (still inefficient, since the work is lazy, but is going to be done regardless)
- Implied, but spend time optimizing the headers!
I’ve done #4 and the only definitions in my headers are templates which need to be templates. Everythign else is declared. I could use more pimpl designs, but then I’d be changing the code just to optimize these includes and I’ll only do that if I have to.
I’m curious about the status of the first two suggestions, but I’d also like to discuss another option.
Cling’s interpreter has a method for storing and diffing states, but it doesn’t have a method (that I can find) for loading states. How reasonable would it be to load my header in Cling, serialize Cling’s state for it, and then load it back up at a later time? I’m looking for the fastest possible solution here, so if this can’t work are there any other ideas?
My goal is to keep jank’s startup time under 100ms, rather than the baseline of 1.4 seconds right now.
I appreciate your time.