Как улучшить время компиляции Visual C++?
Я собираю 2 проекта C++ в buildbot, при каждом коммите. Оба файла содержат около 1000 файлов, один - 100 клоков, другой - 170 клоков. Время компиляции сильно отличается от gcc (4.4) до Visual C++ (2008).
Компиляции Visual C++ для одного проекта занимают 20 минут. Они не могут использовать преимущества нескольких ядер, потому что проект зависит от другого. В итоге полная компиляция обоих проектов в Debug и Release, в 32 и 64 битах, занимает более 2,5 часов.
Сборки gcc для одного проекта занимают 4 минуты. Он может быть распараллелен на 4 ядра и занимает около 1 мин 10 сек. Все 8 сборок для 4 версий (Debug/Release, 32/64 бит) из 2 проектов компилируются менее чем за 10 минут.
Что происходит со временем компиляции Visual C++? Они в основном в 5 раз медленнее.
Каково среднее время, которое можно ожидать для компиляции C++ kloc? Мои 7 с / клок с vC++ и 1,4 с / клок с gcc.
Можно ли что-нибудь сделать для ускорения времени компиляции в Visual C++?
12 ответов
Одна вещь, которая замедляет компилятор VC++, это если у вас есть файл заголовка, который инициализирует конкретные экземпляры нетрива const
типы значений. Вы можете увидеть это с константами типа std::string
или GUID. Это влияет как на компиляцию, так и на время ссылки.
Для одного dll это вызвало замедление в 10 раз. Это помогает, если вы помещаете их в предварительно скомпилированный заголовочный файл или просто объявляете их в заголовке и инициализируете их в файле cpp.
Загляните в антивирусный сканер и поэкспериментируйте с предварительно скомпилированными заголовками, без него вы не увидите VC++ в лучшем виде.
О да, и убедитесь, что папка%TMP% находится в том же разделе, в который записана ваша сборка, поскольку VC++ создает временные файлы и перемещает их позже.
Проекты, зависящие друг от друга, не подразумевают, что распараллеливание невозможно. Системы сборки достаточно умны, чтобы понять и избежать критических зависимостей, иначе gcc не сможет использовать 4 ядра.
Итак (в дополнение к другим шагам), почему бы просто не попробовать включить многопроцессорную обработку в Visual Studio с помощью /MP (см. http://msdn.microsoft.com/en-us/library/bb385193.aspx).
Как вы строите проекты Visual Studio? Вы просто запускаете ide (devenv) с проектом и /build
или у вас есть make-файл, похожий на тот, который я предполагаю, что вы используете для gcc. Я предполагаю, что обе сборки используют одинаковый make-файл, но я подумал, что стоит проверить.
Используете ли вы предварительно скомпилированные заголовки для любого компилятора? Если вы НЕ используете предварительно скомпилированные заголовки для VS, то вы можете переключиться на их использование. Лично я бы рекомендовал использовать #pragma hdrstop
подход, а не один заголовочный файл "все включено", но если вы в настоящее время НЕ используете предварительно скомпилированные заголовки и хотите попробовать его в единственном заголовочном файле "все включено", который принудительно включен (используя /FI
переключатель командной строки компилятора) может быть быстро протестирован без каких-либо изменений кода.
Я написал об обоих /FI
а также #pragma hdrstop
здесь: http://www.lenholgate.com/blog/2004/07/fi-stlport-precompiled-headers-warning-level-4-and-pragma-hdrstop.html
Это не прямой ответ на вопрос, но в моей компании мы используем IncrediBuild для распределенной компиляции. Это действительно ускоряет процесс компиляции. http://incredibuild.com/visual_studio.htm
Книга Джона Лакоса "Разработка программного обеспечения для крупномасштабного C++" содержит множество советов по структурированию вашего кода и дизайна для крупномасштабных проектов. Включая много советов по ускорению компиляции. Не имеет прямого отношения к Visual C++, но в любом случае стоит прочитать.
Я написал две статьи о методах, которые сокращают время компиляции. Среди этих методов - публикация предварительно скомпилированных заголовков и сборок Unity, которые могут помочь вам улучшить время компиляции. Они поставляются со скриптами CMake, которые обрабатывают методы прозрачно.
Прежде всего, в большинстве случаев вы можете создавать отладочные и выпускать конфигурации одного и того же проекта параллельно.
Также то, что вы описываете, звучит ужасно медленно - похоже, что вы не используете предварительно скомпилированные заголовки в VC++ или используете их неправильно - они специально предназначены для сокращения времени компиляции.
Возможно, есть проблема с проверкой зависимостей, если только вы не выполняете полную перестройку.
Вы могли бы сделать несколько статических библиотек. Поместите код, который редко изменяется в библиотеки.
Самые медленные части построения программы:
- Открытие и закрытие файлов.
- Разбор и перевод исходных файлов.
Как правило, этапы создания ссылок и создания исполняемых файлов самые быстрые.
Вы определили:
- какие фазы самые медленные?
- Какие файлы медленнее всего компилировать?
Помните, что при определении эффективности всегда указывайте профиль (так или иначе).
Компилируйте и связывайте по одному файлу cpp за раз, даже если изменения файла заголовка влияют на несколько файлов cpp. Это может быть достигнуто с помощью визуального макроса студии:
Dim WithEvents myTimer As Timers.Timer
Sub CompileAndLinkCurrentCppFile()
DTE.ExecuteCommand("Build.Compile")
myTimer = New Timers.Timer
myTimer.Interval = 0.05
myTimer.Start()
End Sub
Sub myTimer_Elapsed(ByVal ee As Object, ByVal dd As Timers.ElapsedEventArgs) Handles myTimer.Elapsed
If DTE.Solution.SolutionBuild.BuildState <> vsBuildState.vsBuildStateInProgress And DTE.Solution.SolutionBuild.LastBuildInfo <> 1 Then
myTimer.Stop()
DTE.ExecuteCommand("Build.Link")
End If
End Sub
Не знаю, по-прежнему ли это проблема, и сколько улучшений вы получили в menatime, но если он все еще остается в силе, msbuild не знает, как организовать одновременно в одном проекте (каждый cpp должен быть отдельно собран, если у вас нет кодеков - кодгены лучше всего переносить в отдельный проект) вам нужно скачать комплект для разработки драйверов или.NET SSCLI, так как они оба имеют nmake, сборка которого, как известно, хорошо парализует вещи. В SSCLI уже была настроена сборка сборки, не помню, если у DDK есть примеры сборки, нужно ли начинать с нуля.
Также немного устаревшая статья о распараллеливании MSBuild не углубляется в детали, но упоминает некоторые различия между фактическим msbuild и msbuild + sln. Если /MP против /Gm была единственной проблемой, то вам, возможно, придется сделать небольшой скрипт или C# exe для редактирования файлов.proj для лабораторной сборки. Или используйте явное переопределение строки cmd в проектах и используйте эту опцию из env var.
Вы строите на одной машине? Вы используете ту же ОС? Я видел разницу в скорости в 3-10 раз при сравнении GCC в Cygwin и GCC на машине VirtualBox, работающей на Windows, на которой размещается Cygwin.
Кажется очень странным, что такая разница была бы... но нет никаких причин, по которым вы не можете воспользоваться преимуществами многоядерности в Visual!
В основном у вас есть 4 режима компиляции: (Отладка / Выпуск)x(32 бита /64 бита), каждый из которых полностью независим от другого, вы можете отлично запустить 4 параллельно, полностью используя все доступные 4 ядра. Или просто попробуйте многопроцессорный подход на Visual Studio тоже.
Однако это не собирается сокращать это. 150 минут против 10 минут - огромный разрыв. Исходя из моего личного опыта, есть 2 основных фактора, сокращающих время компиляции:
- иметь все файлы, используемые на локальном диске (при необходимости используя репликацию с удаленных), и все файлы, созданные локально (.o.so)
- используйте все имеющиеся в вашем распоряжении ядра и, если сможете, даже перейдите на Multi Machines (distcc и т. д.)