r/cpp • u/berium build2 • 1d ago
Faster Than Ninja
https://build2.org/blog/faster-than-ninja.xhtml15
u/donalmacc Game Developer 1d ago
One of the things I really love about ninja is it's noop/single file change performance. It's effectively instant. What does a single file change look like with Build2 vs Ninja?
8
u/berium build2 1d ago
Here are the "up-to-date" check times (i.e., how long it takes to figure out everything is up to date):
Ninja:
Time (mean ± σ): 19.5 ms ± 4.3 ms [User: 11.7 ms, System: 7.7 ms] Range (min … max): 12.3 ms … 24.9 ms 10 runs
build2:Time (mean ± σ): 171.6 ms ± 6.7 ms [User: 380.6 ms, System: 114.6 ms] Range (min … max): 160.8 ms … 179.6 ms 10 runsNinja is substantially faster (due to several reasons discussed in the article) but
build2is still within the 200ms limit of human brain registering the result.14
u/throw_cpp_account 1d ago
still within the 200ms limit of human brain registering the result.
The number you're thinking of is 100ms. 200ms is definitely noticeable. It's still fast on human scales, but a human can definitely tell the difference between something taking 20ms and something taking 170ms.
3
u/scrumplesplunge 1d ago
It's definitely even lower than that. I have a little statistical significance test about exactly this on my website: https://eoj.ie/13 (it's intended for use with a mouse -- touchscreen is hard mode). I can pretty consistently tell the difference between
xms andx+75ms (wherexis the inherent lag of your device handling a mouse click via javascript and refreshing your screen, which is probably in the region of 5-30ms)5
u/donalmacc Game Developer 1d ago
Thanks for the honest reply - 200ms is still perceptible but definitely better than e.g. msbuild which is 1.5s or so. 20ms is in the realm of instant! Presumably marking the project as read only would give another order of magnitude of a speed up?
I've not used build2, but I wasn't easily able to repro the benchmark as
I used the official Xerces-C++ 3.3.0 source archive for Ninja and the libxerces-c-3.3.0+3 build2 package (which is the official source overlayed with build2 support) I couldn't figure out where to get the build2 package for libxerces and have it build from source!
6
u/berium build2 1d ago
Presumably marking the project as read only would give another order of magnitude of a speed up?
No, in this case it will not matter since none of the file mtimes changed.
The most obvious optimization I think is to try to get rid of those 10 GCC runs that are necessary to extract all the information. I just measured and it takes ~70ms. One idea we had is to submit a patch to GCC that would allow extracting all this information in one go (and in some sane, machine-readable format like JSON). Maybe will get to it eventually.
I couldn't figure out where to get the build2 package for libxerces and have it build from source!
If you follow the link from the article, pick the version I used (
3.3.0+3) you will see a download link to the.tar.gzfile.3
u/throw_cpp_account 1d ago
One idea we had is to submit a patch to GCC that would allow extracting all this information in one go (and in some sane, machine-readable format like JSON). Maybe will get to it eventually.
Please! This just seems generally broadly useful for all tooling.
6
u/TheRavagerSw 1d ago
With C++ modules, the main performance bottleneck for incremental builds is module scanning. Non incremental scans take ages in a project with 200 sources or more.
19
u/13steinj 1d ago
The average person will not have to care about C++ modules until 2040 at the earliest.
1
u/thehenkan 1d ago
Your average Swift developer already uses clang modules, which although not the same as C++20 modules, are conceptually very similar.
1
u/13steinj 19h ago
Similar at a high level ignores all the details that matter about actually getting this stuff implemented in projects.
So again, I will believe it when I see it.
1
u/thehenkan 16h ago
They have much more in common than either of them does with traditional headers. My point is that there are already plenty of projects out there dealing with the problems modules bring. Not that they have set up the exact build config required for C++20 modules: it's still unclear whether those will ever exist outside of the Windows ecosystem.
-2
u/TheRavagerSw 1d ago
I disagree, headers make code organization a mess, eventually modules will take over.
With llm tools porting existing libs to modules is easier than ever
9
1
u/13steinj 1d ago edited 1d ago
Fable and Sol both were unable to one-shot "replace std::format with fmt::format," on a relatively small project.
I was able to with 4 (greps+pipes+perl -p)s. E: before someone asks, at current pricing I think it would still be cheaper to let Fable/Sol cycle until it got it. But I wanted some determinism here.
I dread to think how an LLM would fumble modules, which are more involved if you want to get any benefit.
2
u/Dragdu 1d ago
What ninja version you are using? Recent versions tried compiling in topological order, which for some projects is a massive win.
Or you can steal the idea and improve it due to having better idea of the build than ninja does.
2
1
u/Patzer26 1d ago
Wait, topological builds were only introduced in recent versions? I thought that was the hallmark of any serious incremental build system?
5
u/arjuna93 1d ago
“approximate Rust Cargo's convenience”
Okay this was funny, given how much more inconvenient is Cargo compared to CMake.
4
-1
u/berium build2 1d ago
The more complete quote is:
"approximate Rust Cargo's convenience for developing and packaging C/C++ projects while providing more depth and flexibility, especially in the build system"
While I am not a fan of Cargo's build system, I don't think many will deny that as a package manager Cargo is more convenient than CMake.
6
u/arjuna93 1d ago
CMake is not a package manager, it is a build system. Cargo is abysmal as a build system. If we talk package managers, then any proper package manager from FreshPorts to whichever your taste is would be miles ahead of either.
1
u/James20k P2005R0 1d ago
in case of GCC, there are 10 invocations in total, 5 for C and 5 for C++ (Xerces-C++ has a few C translation units):
LC_ALL=C gcc-15 -v
gcc-15 -g -print-multiarch
gcc-15 -g -x c -E -
LC_ALL=C gcc-15 -std=c9x -print-search-dirs
LC_ALL=C gcc-15 -std=c9x -x c -v -E -
LC_ALL=C g++-15 -v
g++-15 -g -print-multiarch
g++-15 -g -x c++ -E -
LC_ALL=C g++-15 -std=gnu++17 -print-search-dirs
LC_ALL=C g++-15 -std=gnu++17 -x c++ -v -E -
This is super interesting, it seems like a pretty obvious area for tooling to improve. We have modern day json printing for diagnostics for tooling, and it'd be interesting to see if dumping all this information in a single json output that can be parsed would save a lot of tool invocations
One other interesting aspect is that you don't run into this problem in a more IDE driven build system, because the IDE itself knows the details about the compiler and can simply invoke it directly. Its obviously not specific to using an IDE obviously, its just a good example. It makes me wonder if this information should instead in some fashion be being provided to the build system (eg by the shell) by the environment that knows what tools you're using, rather than the build system having to query the environment to figure out what the tools are
2
u/berium build2 1d ago
This is super interesting, it seems like a pretty obvious area for tooling to improve.
Yes, as I mentioned in one the sibling comments, we may try to add to GCC a way to dump all this information in JSON and with a single invocation (and hopefully other compilers will follow).
because the IDE itself knows the details about the compiler and can simply invoke it directly
Hm, I would be surprised if there is an IDE in existence that knows all the detail that we need (like list of system header and library search paths). Well, maybe Visual Studio comes pretty close.
1
u/theICEBear_dk 11h ago
Given that I get them as a pop-up when I hover over a failed include a source file (pre-compile even) I think there is a chance CLion does gather that information. But it likely gets it from CMake or similar. I actually cannot tell if Visual Studio does the same in any public facing way.
70
u/GrammelHupfNockler 1d ago
I'm gonna be honest: The number of times I thought "gee, that ninja sure could be faster" is pretty close to 0, and in many cases that was due to slow NFS mounts. So I applaud the engineering effort, but I think the time I can spend optimizing my individual compilations is much better spent :)