-
Notifications
You must be signed in to change notification settings - Fork 4
Description
What we have
With CMake we have 3 build options provided by Cmake:
Release, builds with-O3, doesn't feature any debug symbolRelWithDebInfo, builds with-O2, features debug symbolsDebug, builds without-O, features debug symboles
Well, there are more like MinSizeRel but we never used that and I never used that for Unvanquished, so I won't mention it.
Alongside that we provide the USE_DEBUG_OPTIMIZE variable that enables -Og. The big difference with RelWithDebInfo and Debug with USE_DEBUG_OPTIMIZE is that the later still enables assertions.
With build with RelWithDebInfo because we want to ship debug symbols because of breakpad. But then it means we build release builds with -O2, I see no reason to not use -O3. We also enable LTO in releases and uses -ffast-math by default.
My experience
On my end here when debugging/testing/profiling I use all those build options for various purpose :
Debug, rare, usually by mistake, or when I want to really step line by line in a debugger.DebugwithUSE_DEBUG_OPTIMIZE, the profile I use the most: keeps assertions enabled, keeps debug symbols, and optimizations are good enough for profiling to be meaningful (unlikeDebug), sometime enabling LTO, sometime not (mostly to reduce link time, sometime to better step the code)RelWithDebInfo: less used, when I want to look at something release-like, usually used with LTO enabled.Release, when I want to benchmark what can do our engine in the better options possible, usually combined with-march=native, LTO enabled and even using some vendor-specific compiler.
About LTO
about LTO, it is really a big deal, for sure it changes a lot the shape of the code between the source and the produced binary, but the benefits are so strong I will not defend the removal of it.
- With our architecture of shipping framework libraries in engine repository for the game, our only change of optimizing them is to use LTO.
- LTO reduces the binary size in a very impressive manner!
Here are some binary size comparison (daemon client) with different build profiles (RelWithDebInfo not being stripped):
| build profile | binary size |
|---|---|
| RelWithDebInfo | 63187776 |
| RelWithDebInfo LTO | 39726360 |
| Release | 4205624 |
| Release LTO | 3379952 |
| MinSizeRel | 2939960 |
| MinSizeRel LTO | 2464800 |
We enabled LTO in release builds 4 years ago in September of 2020: 2db798d .
We already released Unvanquished 0.52, 0.52.1, 0.53, 0.53.1, 0.53.2, 0.54 and 0.54.1 with LTO, without problems.
About -O3
I see no reason to not enable -O3 in release builds.
I also have some pikachu defense for enabling it, this is still pikachu defense but it is not that invalid in such context:
- Being concerned that
-O3may not keep the expected program behaviour would face cognitive dissociation with enabling-ffast-mathby default. - Being concerned that
-O3may make debugging harder would face cognitive dissociation with enabling LTO in releases.
About testing -O3
Except Debug profile without optimization, I use intensively all named build profiles, so I use intensively -O3 and never experienced something bad caused by it. I consider -O3 well tested.
Where to enable -O3?
I see no compelling reasons to not use -O3 in our release builds. Now one question may surface:
- Should we enable
-O3in our CMake file for allRelWithDebInfobuilds. - Should we only do that in release scripts?
I'm in favor of the first option: people should debug what we release.