"Забързване" на компилатора
Привет, колеги!
Вчера пробвах няколко варианта за компилиране, като целта ми беше да видя на практика ефекта им върху времето за компилация. Получиха се интересни резултати и затова реших да ги споделя и тук.
За тест използвах проекта от курса, а това са времената, които засякох на машината ми (i7, 6-cores + HT, Ubuntu 20.04), използвайки time командата, напр.:
$ time(cmake .. && make)
Command | Time, s |
---|---|
cmake .. && make |
17.151 |
rm -rf * && cmake .. && make |
1.099 [rebuild from ccache] |
cmake -DFAST=1 .. && make |
7.243 |
cmake .. && make -j12 |
5.967 |
cmake -DFAST=1 .. && make -j12 |
5.815 |
cmake .. && cmake --build . -j12 |
5.742 |
cmake -DFAST=1 .. && cmake --build . -j12 |
5.870 |
cmake -G"Ninja" .. && ninja -j 12 |
4.220 |
cmake -DFAST=1 -G"Ninja" .. && ninja -j 12 |
2.619 |
Забележки:
- -DFAST=1 активира CCache и Unity Build в CMakeList.txt (някъде в началото му):
if(FAST) # cmake .. -DFAST=1 message(STATUS "Unity and CCache enabled") set(CMAKE_CXX_COMPILER_LAUNCHER ccache) set(CMAKE_UNITY_BUILD true) endif(FAST)
-
-G"Ninja" сменя билд системата от "Unix Makefiles" на Ninja - "Ninja ... Its distinguishing goal is to be fast.". За да се използва, трябва предварително да се инсталирара на системата: sudo apt install ninja-build, като билдването става с командата ninja (вместо с make или cmake --build .), а като доп. параметър може да се зададе и в колко треда да рънва (напр. -j 12)
-
CCache - "a fast C/C++ compiler cache.". Прави точно това - кешира резултата от последната компилация на даден файл и спестява прекомпилирането му. Това работи дори и ако изтрием всички файловe от build папката, както е видно от теста на втори ред. Инсталира се допълнително на системата с: sudo apt install ccache. Ако по някаква причина искаме ръчно да зачистим кеша (например между отделните тестове), може да го направим с командата "ccache -C" (с главна буква C).
-
UNITY_BUILD: "... target source files will be combined into batches for faster compilation. This is done by creating a (set of) unity sources which #include the original sources, then compiling these unity sources instead of the originals.". По този начин се спестява инклудването и прекомпилирането на повтарящи се хедъри и се облекчава линкването. Използването му може да доведе и до някои проблеми - ето една добра статия по темата от Виктор Кирилов (той има и няколко talk-a в yuotube на същата тема). Аз не се натъкнах на проблеми, но и проектът не е кой-знае колко голям.
-
За всички паралени компилации съм използвал 12 треда за да избегна дефолтните стойности при различните билд системи.
-
Между отделните тестове съм зачиствал съдържанието на build папката (rm -rf *) и ccache-a (ccache -C)
Коментари по резултатите:
-
Използването на UNITY_BUILD за тестовия проект подобри времето за компилация само в два случая: компилиране в един тред (17s -> 7s) и при билдване с Ninja (4.2 --> 2.6s)
-
make и cmake --build . са идентични като скорост както с един, така и с няколко треда и не се влияят от UNITY_BUILD
-
CCache смъква времената за компилция значително, но се опасявам, че ползите от него не са универсални, а са в ограничени сценарии - без промени по файловете, затриване на build папката (защото и make/cmake/ninja не прекомпилират непроменените юнити) или използване на един модул в множество проекти (в този случй ще се използва кеша от билда за друг проект). От друга страна, не забелязах да пречи (освен да пълни диска, може би).
-
Ninja отвява конкуренцията, като дори и без UNITY_BUILD е с около 30% по-бърза от make/cmake (5.8 -> 4.2s), a с UNITY_BUILD е над 50% по-бърза (т.е. отнема наполовина по-малко време: 5.8 -> 2.6s). Не съм забелязал никакви проблеми при използването ѝ до момента.