Как ВЫ сокращаете время компиляции и время компоновки для проектов 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 также имеет опцию "Показать включения", которая может дать вам представление о том, какие исходные файлы содержат много заголовков и какие файлы заголовков включены чаще всего.

Для очень распространенных включений рассмотрите возможность помещения их в предварительно скомпилированный заголовок.

Я использую Unity Builds (Screencast, расположенный здесь).

Вопрос о скорости компиляции достаточно интересен, так что Страуструп имеет его в своем 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 означает создание временного кода канала)

Другие вопросы по тегам