Positive Technologies corporate blog
High performance
Website development
March 2013 7

Оптимизация сборки крупного проекта

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

В процессе разработки и дальнейшего развития крупного разнородного проекта мы также столкнулись с проблемами оптимизации. Но должны же быть способы уменьшить время сборки? Мы решили найти способ решения этой задачи. Собрать за 60 секунд!..



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

Начало


Залог успешной оптимизации проекта — его автоматизация. Мы использовали известную систему автоматизации CMake, на которой, как на фундаменте дома, надстраивали различные технологии.

Вот, что мы имели в начале пути:

  • 176 проектов C++ и C# (в соотношении приблизительно 60% к 40%);
  • 100 МБ исходников;
  • 18 000 файлов (> 3 млн строк);
  • MSVS;
  • сервер (8 CPU, обычный диск на 10 рейде HDD, 12 ГБ ОЗУ);
  • виртуальная машина.

Все это собиралось 12 минут.

После оптимизации кода по результатам статического анализа, удаления лишних директив #include, перекомпоновки исполняемых модулей, динамических и статических библиотек время сборки уменьшилось до 8 минут. Далее речь пойдет именно об оптимизации процесса сборки, когда все возможные улучшения кода уже реализованы.

Чтобы достичь максимальной скорости, мы использовали два подхода к оптимизации: аппаратный и программный. Как мы покажем далее, первый совсем не исключает второго, но дополняет его.

Программный способ


Типовые методы

Про типовые методы настройки VisualStudio написано очень много на просторах Интернета, поэтому коснемся их вскользь.

  • Ключ /MP, который позволяет запускать несколько процессов компиляции одновременно.
  • Ключ /Z7, который отключает генерацию отладочной информации, в результате чего компиляция производится быстрее.

Более интересна технология, известная как UnityBuild. Это один из самых эффективных программных методов оптимизации, ускоряющий сборку на 30%. В процессе работы мы слегка усовершенствовали эту технологию и назвали новую, улучшенную версию Smart UnityBuild.

Стандартная технология работает следующим образом: в каждом файле *.cmake каждого проекта используется модуль unity_build.cmake, который направлен на папку, содержащую все *.cpp-файлы, обрабатывает их и объединяет в новый «общий» файл *.cpp. Далее создается файл *.vcproj, содержащий этот единый *.cpp.

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

Схематически это выглядит так:



В результате использование нашей технологии Smart UnityBuild позволило ускорить сборку до 4 мин. 40 сек.



UnityBuild + PCH (Incredibuild)

Очевидно, что использование PCH совместно с технологией UnityBuild, что называется в лоб, ничего не даст. Но все же есть способ обмануть VisualStudio. Для этого нужно искусственно вынести файлы, использующиеся в проекте несколько раз (у нас это *.boost и *.spl), в отдельный проект, собрать из него Precompiled Headers и подкладывать их в основной проект, в результате VisualStudio будет «думать», что это настоящие PCH. При использовании технологии Unity Build с Precompiled Headers и ключом LP можно добиться значительного сокращения времени сборки: в нашем случае — с 12 мин. до 4 мин. 38 сек. (без ключа LP — 5 мин. 53 сек.).

Аппаратный способ


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

SSD RAID0 x 7

Наилучшего результата по времени сборки удалось добиться при использовании 7 дисков SSD в Raid0-массиве и RAMDisk: длительность сборки проекта составила около 6 минут.

32 CPU x 3 GHz

Прирост в быстродействии более чем в два раза по сравнению со стандартным значением времени (7 мин. 45 сек.) дает использование 32 процессоров с технологией Hyper Threading (3 мин. 22 сек.).



Итог


Соединив все средства от опций Visual Studio до использования SSD дисков, мы смогли добиться снижения времени сборки проекта с 12 минут до 1 мин. 45 сек. Таким образом, заявленная цель — уложиться в 60 секунд — осталась невыполненной, но мы не расстроились :) Снижение времени, затрачиваемого на сборку проекта, более чем в 6 раз — это хороший результат.

Вот как выглядит прогресс сборки нашего проекта:



Из диаграммы видно, что достижению еще большей скорости мешают несколько длительных по времени процессов. Это линковка больших модулей, распараллелить которую невозможно (только частично попытка сделать это есть в MSVS 2012), но можно разбить их программно на несколько мелких, уменьшить количество и размер статических библиотек.

Вот, собственно, и все. Перед нами не стояло цели объять необъятное, и некоторые технические аспекты оптимизации не вошли в статью. Мы готовы раскрыть подробности и ответить на все вопросы (в том числе по исходникам cmake) в комментариях. Cпасибо за внимание!

P. S. Мысли, изложенные в данном топике, легли в основу презентации, которую Виктор Стрелков (руководитель отдела исследований и контроля качества Positive Technologies) представил на конференции CEE-SECR в ноябре 2012 года. Запись трансляции этого выступления можно посмотреть на сайте мероприятия.
+44
22.6k 98
Comments 45
Top of the day