GCC / Сделать оптимизацию времени сборки - PullRequest
10 голосов
/ 02 апреля 2009

У нас есть проект, который использует gcc и make files. Проект также содержит один большой подпроект (SDK) и множество относительно небольших подпроектов, которые используют этот SDK и некоторую общую инфраструктуру.

Мы используем предварительно скомпилированные заголовки, но это помогает только для ускорения повторной компиляции.

Существуют ли какие-либо известные методы и инструменты, помогающие оптимизировать время сборки? Или, может быть, вы знаете некоторые статьи / ресурсы по этой или смежным темам?

Ответы [ 10 ]

15 голосов
/ 02 апреля 2009

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

Не касаясь кода, вы можете добавить в него больше возможностей компиляции. Используйте ccache, чтобы избежать перекомпиляции уже скомпилированных файлов, и distcc, чтобы распределить время сборки среди большего количества машин. Используйте make -j, где N - количество ядер + 1, если вы компилируете локально, или большее число для распределенных сборок. Этот флаг будет запускать более одного компилятора параллельно.

Рефакторинг кода. Предпочитаю предварительную декларацию для включения (простой) Отсоедините как можно больше, чтобы избежать зависимостей (используйте идиому PIMPL).

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

7 голосов
/ 02 апреля 2009

Лучшее, что я могу придумать с make, - это опция -j. Это говорит make запускать как можно больше заданий параллельно:

make -j

Если вы хотите ограничить число одновременных заданий n , вы можете использовать:

make -j n


Убедитесь, что зависимости правильные, поэтому make не запускает задания, которые ему не нужны.


Еще одна вещь, которую необходимо учитывать, - это оптимизация, которую gcc делает с переключателем -O. Вы можете указать различные уровни оптимизации. Чем выше оптимизация, тем дольше время компиляции и компоновки. Проект, с которым я работаю, занимает 2 минуты, чтобы связать с -O3, и полминуты с -O1. Вы должны убедиться, что вы не оптимизируете больше, чем нужно. Вы можете собрать без оптимизации для сборок разработки и с оптимизацией для сборок развертывания.


Компиляция с отладочной информацией (gcc -g), вероятно, увеличит размер вашего исполняемого файла и может повлиять на время сборки. Если вам это не нужно, попробуйте удалить его, чтобы увидеть, влияет ли оно на вас.


Тип связывания (статический или динамический) должен иметь значение. Насколько я понимаю, статическое связывание занимает больше времени (хотя я могу ошибаться здесь). Вы должны увидеть, влияет ли это на вашу сборку.

4 голосов
/ 23 апреля 2009

Из описания проекта я предполагаю, что у вас есть один Makefile на каталог и вы используете рекурсивный make много. В этом случае методы из «Рекурсивное создание считают вредным» должны очень помочь.

2 голосов
/ 25 марта 2012

Вы можете рассмотреть возможность перехода на другую систему сборки (которая, очевидно, не будет работать для всех), например, SCons. SCons намного умнее, чем делают. Он автоматически сканирует зависимости заголовка, поэтому у вас всегда есть наименьший набор зависимостей перестроения. Добавляя строку Decider('MD5-timestamp') в ваш файл SConstruct, SCons сначала просматривает метку времени файла, и если он новее, чем ранее созданная метка времени, он будет использовать MD5 файла, чтобы убедиться, что вы действительно что-то изменили , Это работает не только с исходными файлами, но и с объектными файлами. Это означает, что, например, если вы измените комментарий, вам не нужно повторно ссылаться.

Автоматическое сканирование заголовочных файлов также гарантирует, что мне никогда не придется набирать scons --clean. Это всегда делает правильно.

2 голосов
/ 27 мая 2009

Кроме того, вы, вероятно, захотите, чтобы ваши файлы исходного кода были как можно меньшими и самодостаточными, насколько это возможно / выполнимо, то есть предпочитаете много меньших объектных файлов, а не один огромный объектный файл.

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

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

Кроме того, вы также можете захотеть использовать золотой компоновщик GNU , который намного эффективнее для компиляции кода C ++ для целей ELF.

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

2 голосов
/ 02 апреля 2009

Если у вас есть несколько доступных компьютеров, gcc хорошо распределяется по distcc .

Вы также можете дополнительно использовать ccache .

Все это работает с очень небольшими изменениями make-файлов.

0 голосов
/ 28 января 2014

Использование небольших файлов не всегда может быть хорошей рекомендацией. Диск имеет размер сектора не менее 32 или 64 КБ, а файл занимает по крайней мере один сектор. Таким образом, 1024 файла размером 3K (небольшой код внутри) на самом деле займет 32 или 64 мегабайта на диске вместо ожидаемых 3 мегабайт. 32/64 мегабайт, которые должны быть прочитаны приводом. Если файлы разбросаны по диску, вы увеличиваете время чтения еще больше со временем поиска. Это помогает с Disk Cache, очевидно, до предела. Предварительно скомпилированный заголовок также может помочь в этом.

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

0 голосов
/ 29 декабря 2010

Вы можете использовать распределенный компилятор distcc , чтобы сократить время сборки, если у вас есть доступ к нескольким машинам. Вот статья из IBM developerWorks, связанная с distcc, и о том, как вы можете ее использовать: http://www.ibm.com/developerworks/linux/library/l-distcc.html

Еще один способ сократить время сборки - использовать предварительно скомпилированные заголовки. Вот отправная точка для gcc .

Также не забывайте использовать -j при сборке с make, если ваша машина имеет более одного процессора / ядра (в два раза больше числа ядер / процессора просто отлично).

0 голосов
/ 02 апреля 2009

http://ccache.samba.org/ ускоряет большое время.

Я работаю над проектом среднего размера, и это единственное, что мы делаем для ускорения времени компиляции.

0 голосов
/ 02 апреля 2009

Если у вас есть локальная сеть с компьютерами разработчика, возможно, вам следует попробовать внедрить решение распределенного компилятора, например distcc .

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

...