Как ВЫ сокращаете время компиляции и время компоновки для проектов Visual C++ (нативный C++)?
Как ВЫ сокращаете время компиляции и связывания времени для проектов VC++ (нативный C++)?
Пожалуйста, укажите, относится ли каждое предложение к отладке, выпуску или обоим.
12 ответов
Это может показаться очевидным для вас, но мы стараемся использовать как можно больше предварительных объявлений, даже если для этого требуется записать длинные имена пространств имен, в которых есть тип (ы):
// Forward declaration stuff
namespace plotter { namespace logic { class Plotter; } }
// Real stuff
namespace plotter {
namespace samples {
class Window {
logic::Plotter * mPlotter;
// ...
};
}
}
Это значительно сокращает время компиляции и на других компиляторах. Действительно это относится ко всем конфигурациям:)
Используйте шаблон Handle/Body (также известный как "pimpl", "adapter", "decorator", "bridge" или "wrapper"). Выделяя реализацию ваших классов в ваши файлы.cpp, их нужно скомпилировать только один раз. Для большинства изменений не требуется вносить изменения в заголовочный файл, так что это означает, что вы можете вносить довольно обширные изменения, требуя перекомпиляции только одного файла. Это также способствует рефакторингу и написанию комментариев и модульных тестов, так как время компиляции сокращается. Кроме того, вы автоматически разделяете проблемы интерфейса и реализации, чтобы интерфейс вашего кода был упрощен.
Если у вас есть большие сложные заголовки, которые должны включаться большинством файлов.cpp в ваш процесс сборки и которые не изменяются очень часто, вы можете предварительно скомпилировать их. В проекте Visual C++ с типичной конфигурацией это просто вопрос включения их в stdafx.h. У этой функции есть свои недостатки, но библиотеки, которые в полной мере используют шаблоны, как правило, содержат много материала в заголовках, и предварительно скомпилированные заголовки - самый простой способ ускорить сборку в этом случае.
Эти решения применимы как к отладке, так и к выпуску, и ориентированы на кодовую базу, которая уже большая и громоздкая.
Предварительные декларации являются распространенным решением.
Распределенное здание, такое как с Incredibuild, является победой.
Выдвижение кода из заголовков в исходные файлы может работать. Небольшие классы, константы, перечисления и т. Д. Могут начинаться в заголовочном файле просто потому, что его можно было использовать в нескольких блоках компиляции, но в действительности они используются только в одном и могут быть перемещены в файл cpp.
Решение, о котором я не читал, но которое использовал, заключается в разделении больших заголовков. Если у вас есть несколько очень больших заголовков, взгляните на них. Они могут содержать связанную информацию, а также могут зависеть от множества других заголовков. Возьмите элементы, которые не зависят от других файлов... простые структуры, константы, перечисления и предварительные объявления и переместите их из the_world.h
в the_world_defs.h
, Теперь вы можете обнаружить, что многие из ваших исходных файлов теперь могут включать только the_world_defs.h
и избегать всех этих накладных расходов.
Visual Studio также имеет опцию "Показать включения", которая может дать вам представление о том, какие исходные файлы содержат много заголовков и какие файлы заголовков включены чаще всего.
Для очень распространенных включений рассмотрите возможность помещения их в предварительно скомпилированный заголовок.
Вопрос о скорости компиляции достаточно интересен, так что Страуструп имеет его в своем FAQ.
Мы используем Incredibuild от Xoreax для параллельного запуска компиляции на нескольких машинах.
Также интересная статья от Неда Батчелдера: http://nedbatchelder.com/blog/200401/speeding_c_links.html (о C++ в Windows).
Наши машины для разработки являются четырехъядерными, и мы используем Visual Studio 2008 с поддержкой параллельной компиляции. Я не уверен, могут ли все издания VS сделать это.
У нас есть файл решения с примерно 168 отдельными проектами, и на нашем четырехъядерном компьютере такая компиляция занимает около 25 минут по сравнению с 90 минутами на одноядерных ноутбуках, которые мы даем летним студентам. Не совсем сопоставимые машины, но вы поняли:)
В Visual C++ есть метод, который некоторые называют Unity, который значительно улучшает время соединения за счет уменьшения количества объектных модулей.
Это включает в себя конкатенацию кода C++, обычно в группах по библиотекам. Это, конечно, делает редактирование кода намного более сложным, и вы столкнетесь с коллизиями пространства имен, если не будете их использовать должным образом. Это удерживает вас от использования "использования пространства имен foo";
Несколько команд в нашей компании разработали системы, позволяющие брать обычные файлы C++ и объединять их во время компиляции в качестве этапа сборки. Сокращение времени соединения может быть огромным.
Еще одна полезная техника - это капля. Я думаю, что это похоже на то, что описал Мэтт Шоу.
Проще говоря, вы просто создаете один файл cpp, в который вы включаете другие файлы cpp. У вас может быть две разные конфигурации проекта, одна обычная и одна большая. Конечно, blobbing накладывает некоторые ограничения на ваш код, например, имена классов в безымянных пространствах имен могут конфликтовать.
Один из способов избежать перекомпиляции всего кода в BLOB-объекте (как упоминал Дэвид Родригес) при изменении одного файла cpp - это иметь ваш "рабочий" BLOB-объект, созданный из файлов, измененных недавно, и других обычных BLOB-объектов.
Большую часть времени мы используем blobbing на работе, и это сокращает время сборки проекта, особенно время компоновки.
Время компиляции:
Если у вас есть IncrediBuild, время компиляции не будет проблемой. Если у вас нет IncrediBuild, попробуйте метод "построения единства". Он объединяет несколько файлов cpp в один файл cpp, что сокращает время компиляции.
Время ссылки:
Метод "построения единства" также способствует сокращению времени соединения, но не намного. Тем не менее, вы можете проверить, включены ли "Общая глобальная оптимизация" и "LTCG", в то время как эти флаги делают программу быстрой, они действительно делают ссылку МЕДЛЕННОЙ.
Попробуйте отключить "Целую глобальную оптимизацию" и установить для LTCG значение "По умолчанию", время соединения может быть уменьшено на 5/6.
(LTCG означает создание временного кода канала)