включить охранники — Как сократить время компиляции для большой библиотеки C ++ отдельных файлов .cpp?

Мы разрабатываем Библиотека C ++ в настоящее время более 500 сотен отдельных файлов .cpp. Каждый из них компилируется и архивируется в статическую библиотеку. Даже при параллельной сборке это занимает несколько минут. Я хотел бы сократить это время компиляции.

Каждый файл состоит в среднем из 110 строк с функцией или двумя внутри. Однако для каждого файла .cpp существует соответствующий заголовок .h, который часто включается во многие файлы .cpp. Например, A.h может быть включен A.cpp, B.cpp, C.cpp, и так далее.

Я бы сначала хотел профиль процесс компиляции. Есть ли способ узнать, сколько времени тратится на то, что делать? Я беспокоюсь, что много времени тратится впустую, открывая заголовочные файлы только для проверки включаемых защит и игнорирования файла.

Если такого рода вещи являются виновником, каковы лучшие методы для сокращения времени компиляции?

Я готов добавить новые групповые заголовки, но, вероятно, не желаю изменять этот макет с несколькими файлами, поскольку это позволяет нашей библиотеке также функционировать как по мере необходимости библиотека только для заголовков.

-1

Решение

Если такого рода вещи являются виновником, каковы лучшие методы для сокращения времени компиляции?

Если ваш препроцессор поддерживает #pragma once директива, используйте это. Это гарантирует, что файл .h не будет прочитан более одного раза.

Если нет, используйте #include охранники в .cpp файлах.

Скажи у тебя

хиджры:

#ifndef A_H
#define A_H

...

#endif

Вы можете использовать следующий метод в A.cpp:

#ifndef A_H
#include "A.h"#endif

Вам нужно будет повторить этот шаблон для каждого файла .h. Например.

#ifndef B_H
#include "B.h"#endif

#ifndef C_H
#include "C.h"#endif

Вы можете прочитать больше об использовании #include охранники в .cpp файле на Какова функция include guard в .cpp (не в .h)?.

2

Другие решения

Я не знаю, делаете ли вы это уже, но использование предварительных объявлений вместо включений в заголовки должно увеличить скорость компиляции. Смотрите этот вопрос для получения дополнительной информации:

Следует ли использовать предварительные декларации вместо включений везде, где это возможно?

Другой способ уменьшить время компиляции — использовать ccache, Кэширует результаты предыдущих компиляций.

https://ccache.samba.org

2

Это действительно трудно сказать.

Я работал над улучшением времени компиляции нашего проекта на работе и обнаружил, что один файл занял 15 минут (при компиляции в -O2, но около 15 секунд -O0) и компилируется дважды, поэтому для общего времени компиляции около 60-70 минут это было примерно вдвое меньше. Отключение ОДНОЙ функции оптимизации привело к тому, что один файл сократился до 20 секунд вместо 15 минут … Этот файл создавал одну функцию, сгенерированную компьютером, и несколько десятков тысяч строк, что заставляет компилятор совершать магические действия. длинные вещи (предположительно, некоторый алгоритм O (N ^ 2)).

Это также может произойти, если у вас есть небольшая функция, которая затем по очереди вызывает множество мелких функций, которые, в конечном итоге, через слои встраивания превращаются в большой файл.

В других случаях я обнаружил, что сокращение количества файлов и помещение большего количества кода в один файл работает лучше.

В целом, мой опыт (как с моим собственным проектом компилятора, так и с компиляторами других людей / компании) заключается в том, что не разбор и чтение файлов занимают время, а различные этапы оптимизации и генерации кода. Вы можете попробовать это, скомпилировав все файлы, используя -fsyntax-only или как там это называется для вашего компилятора. Это ПРОСТО прочитает источник и проверит его синтаксически правильно. Попробуйте также скомпилировать с -O0 если ты еще не Часто конкретный проход оптимизации является проблемой, а некоторые проходы хуже, чем другие, поэтому полезно проверить, какие отдельные проходы оптимизации существуют в конкретном -O опция — в gcc, которая может быть указана с -Q -O2 --help=optimizers [в этом случае для -O2].

Вам действительно нужно выяснить, на что компилятор тратит время. Нет смысла менять код, если проблема в том, что вы проводите большую часть времени, оптимизируя код. Нет смысла сокращать оптимизаторы, если время потрачено на разбор, а оптимизация не добавляет дополнительного времени. Без фактического построения ВАШЕГО проекта очень сложно сказать наверняка.

Еще один совет, чтобы проверить top чтобы увидеть, использует ли каждый ваш процесс компиляции 100% процессор — если нет, то, вероятно, у вас недостаточно памяти на вашем компьютере компиляции. У меня есть опция сборки для моего рабочего проекта, которая «убивает» мой настольный компьютер, выполняя так много памяти, что вся система просто останавливается — даже переключение с одной вкладки на другую в веб-браузере занимает 15-30 секунд. Единственное решение — меньше бегать -j [но, конечно, я обычно забываю, и в этот момент — поэтому, если я не хочу прерывать это, я иду на обед, долгий перерыв на кофе или что-то подобное, пока он не закончится, потому что машина просто непригодна]. Это только для отладочных сборок, потому что сбор отладочной информации для большой базы кода занимает много памяти [очевидно!]

2