Как улучшить производительность ссылок для большого приложения на С++ в VS2005
У нас есть довольно большое приложение на С++, которое состоит из около 60 проектов в Visual Studio 2005. В настоящее время для связи в режиме выпуска требуется 7 минут, и я хотел бы попытаться сократить время. Есть ли советы по улучшению времени соединения?
Большинство проектов компилируются в статические библиотеки, это упрощает тестирование, поскольку каждый из них также имеет набор связанных модульных тестов. Похоже, что использование статических библиотек не позволяет VS2005 использовать инкрементную привязку, поэтому даже при инкрементальной привязке он делает полную ссылку каждый раз.
Будет ли использование DLL для подпроектов иметь значение? Я действительно не хочу проходить через все заголовки и добавлять макросы для экспорта символов (даже используя script), но если он сделает что-то, чтобы сократить время ссылки 7 минут, я обязательно его рассмотрю.
По какой-то причине использование nmake из командной строки немного быстрее и привязка одного и того же приложения к Linux (с GCC) выполняется намного быстрее.
- IDE Visual Studio 7 минут
- Visual С++ с использованием nmake из командной строки - 5 минут
- GCC на Linux 34 секунды
Ответы
Ответ 1
Если вы используете флаг /GL
, чтобы включить оптимизацию всей программы (WPO) или /LTCG
, чтобы включить генерацию кода временного кода. Отключение их приведет к значительному увеличению времени соединения за счет некоторых оптимизаций.
Кроме того, если вы используете флаг /Z7
, чтобы помещать символы отладки в файлы .obj
, ваши статические библиотеки, вероятно, огромно. Использование /Zi
для создания отдельных файлов .pdb
может помочь, если оно не позволяет компоновщику считывать все символы отладки с диска. Я не уверен, действительно ли это помогает, потому что я не сравнивал его.
Ответ 2
См. мое предложение, сделанное в Microsoft: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=511300
Вы должны проголосовать за это! Вот мой последний комментарий к нему:
Да, мы используем инкрементную привязку для создания большинства наших проектов. Для самых больших проектов это бесполезно. Фактически, для привязки этих проектов требуется дополнительное время с добавочной привязкой (2 мин. 50 по сравнению с 2мин44). Мы наблюдали, что он не работает, когда размер файлов ILK большой (наш самый большой проект генерирует иждивене 262144 КБ в выигрыше 32).
Bellow, я перечисляю другие вещи, которые мы пытались сократить время ссылки:
- Явное создание шаблона для уменьшения раздувания кода. Малый выигрыш.
- IncrediLink (IncrediBuild дает интересный выигрыш для компиляции, но почти не выигрывает для ссылки).
- Удалить информацию об отладке для библиотек, которые редко отлаживаются (хороший выигрыш).
- Удалить файл PDB в "Pre-Build Event" (странно он дает интересный выигрыш ex: 2min44 вместо 3min34).
- Преобразование многих библиотек статики в DLL. Важный выигрыш.
- Работа с компьютером, оборудованным множеством ОЗУ, чтобы максимизировать кеш диска. Самый большой выигрыш.
- Большой объект против небольшого объекта. Никакой разницы.
- Изменить параметры проекта (/Ob1,/INCREMENTAL, Включить свертывание COMDAT, Вставить манифест и т.д.). Некоторые дают интересную выгоду другим. Мы стараемся постоянно максимизировать наши настройки.
- Максимизировать внутреннюю связь и внешнюю связь. Это хорошая практика программирования.
- Отдельный программный компонент, который мы можем себе позволить. Вы можете работать в unit test, что ссылка быстро. Но нам все равно нужно взаимодействовать друг с другом, у нас есть устаревший код, и мы работали с сторонним компонентом.
- Используйте секретный переключатель компоновщика /expectedoutputsize: 120000000. Малый выигрыш.
Заметим, что для всех наших экспериментов мы тщательно измеряли время связи. Медленное время соединения серьезно сказывается на производительности. Когда вы выполняете сложный алгоритм или отслеживаете сложную ошибку, вы хотите быстро итеративно выполнить эту последовательность: изменить код, ссылку, отладить трассировку, изменить код, ссылку и т.д.
Еще один момент для оптимизации времени ссылки - это влияние, которое оно оказывает на наш непрерывный цикл интеграции. У нас есть много приложений, которые используют общий код, и мы постоянно работаем над ним. Время соединения всех наших приложений заняло половину времени цикла (15 минут)...
В потоке https://blogs.msdn.microsoft.com/vcblog/2009/09/10/linker-throughput/ были сделаны некоторые интересные предложения для улучшения времени соединения. На 64-битном компьютере почему бы не предлагать возможность полностью работать с файлом в ОЗУ?
Снова, любые предложения, которые могут помочь нам сократить время ссылки, приветствуются.
Ответ 3
Как правило, использование DLL вместо статических библиотек улучшит время компоновки совсем немного.
Ответ 4
Посмотрите Incredibuild от Xoreax. Его распределенная компиляция значительно сократила время полной сборки/ссылки с 40 минут до 8 минут.
Кроме того, у этого продукта есть функция, которую они называют Incredilink, которая должна помочь вам получить инкрементные ссылки, работающие даже со статически связанными библиотеками.
Ответ 5
Я не думаю, что преобразование в DLL было бы полезно.
Вы могли бы попытаться найти варианты, связанные с оптимизацией, и отключить их. Линкер может долгое время просматривать библиотеки для избыточного кода, который он может устранить. Ваше приложение может оказаться больше или медленнее, но это может быть не проблемой для вас.
Ответ 6
Несколько человек сообщили (и я сам заметил), что изменение файла в статически связанной библиотеке отключит инкрементную привязку для всего решения; это похоже на то, что вы видите. См. Комментарии здесь и здесь для получения некоторой информации об этом.
Одним из способов решения этой проблемы является использование Fast Solution Build надстройки. Это может потребовать внесения нескольких изменений в ваше рабочее пространство, но выигрыш определенно стоит того. Для коммерческого решения используйте Xoreax Incredibuild, который в основном включает эту же технологию, но также добавляет другие функции. Я прошу прощения, если я звучу как продавец для Incredibuild - я просто очень довольный клиент.
Ответ 7
У меня были подобные проблемы, связывающие большие приложения с Visual С++ раньше. В моем случае у меня просто не хватило свободной ОЗУ, а чрезмерный пейджинг на диск замедлял процесс связывания. Удвоение моей памяти с 1 ГБ до 2 ГБ значительно улучшилось. Сколько стоит ваш dev box?
Ответ 8
Я только что узнал, что мы случайно определили большую таблицу строк в заголовочном файле, который был включен почти в каждую (статическую) lib. (Я говорю о огромном проекте на С++.) Когда компоновщик создал EXE, это похоже на унификацию таблицы (в EXE только один), или разбор libs навсегда. Помещение таблицы в отдельный файл на С++ заняло пару минут ссылки на относительно медленной машине.
К сожалению, я не знаю, как найти такие вещи, кроме как случайно.
Ответ 9
Для отладочных сборников можно использовать инкрементную привязку, которая может значительно увеличить время ссылок.
К сожалению, есть определенные подводные камни, и VS2005 не предупредит вас.
-
Если вы используете статические библиотеки, инкрементная привязка не будет работать, если вы изменяете часть файла для статической библиотеки. Решение состоит в том, чтобы установить параметр компоновщика "Использовать вкладки зависимостей библиотеки" на "Да" (это то же самое, что и Fast Solution Build в VS2003)
-
Если вы используете pragma-comment-lib для включения библиотеки DLL и задаете относительный путь, а не только lib, то инкрементная привязка перестанет работать. Решение состоит в том, чтобы указать только lib и использовать LIBPATH для компоновщика, чтобы добавить дополнительный lib-путь.
-
Несколько раз файл .ilk будет поврежден (вырастет выше 200 Мбайт), а затем внезапный инкрементный компоновщик будет занимать более 10 раз больше обычного времени. Несколько раз он будет жаловаться на повреждение файла .ilk, но обычно сначала через несколько минут. Решение для меня состояло в том, чтобы настроить следующую команду для события "Build Event" → "Pre-Link Event"
для %% f in ($ (IntDir) *. ilk) do (если "%% ~ zf" GTR "200000000" (del %% f))
Ответ 10
60 libs для ссылки звучат как справедливые. Это может быть немного экстремальной мерой, но это может радикально ускорить процесс. Создайте новое решение с несколькими проектами и добавьте к ним весь исходный код из ваших существующих проектов. Затем создайте и соедините их, а просто сохраните маленькие для тестирования.
Ответ 11
Получите более быстрый компьютер с несколькими процессорами и включите параллельные сборки (это может быть включено по умолчанию). Чтобы обеспечить наибольшую степень параличности, убедитесь, что ваши зависимости проекта верны, и у вас нет ненужных зависимостей.
Ответ 12
Если вы действительно говорите о времени ссылки, то такие вещи, как быстрое построение решений и Xoreax, действительно не помогут много (за исключением Incredilink, который может). Предполагая, что вы действительно измеряете ссылку, начинаете связывать конец, тогда я бы предположил, что количество libs, которое у вас есть, является проблемой.
Эта фаза связи, по крайней мере, первоначально, IO связана с загрузкой всех файлов объектов и lib. Возможно, вы находитесь в ситуации, когда у вас есть 60 библиотек вместе с основным проектом некоторого большого количества файлов .obj. Я подозреваю, что вы просто можете увидеть, по крайней мере частично, типичную медленность Windows при загрузке всех этих файлов lib и .obj.
Вы можете легко проверить это. Возьмите все эти файлы lib и создайте один файл lib как тест. Вместо того, чтобы связываться с 60 из них, связывайтесь с одним и смотрите, где ваше время идет. Это было бы интересно.
NTFS не слишком медленна. Это вряд ли будет 7 м против 32 секунд в Linux медленным, но это может быть частью проблемы. Использование DLL поможет, но вы будете страдать от времени запуска приложения, хотя это будет не так рано. Я был бы уверен, что у вас не будет времени запуска приложений 7 м.
Ответ 13
вы можете попробовать: http://msdn.microsoft.com/en-us/library/9h3z1a69.aspx
В принципе, вы можете запускать сборки проекта параллельно, если у вас несколько ядер.
Ответ 14
Я решил проблему с линией связи и поделился со всеми вами.
Время моего проекта было 7 мин с/Инкрементальное: без ссылки (время связи 7 мин).
Было 15 минут с/инкрементальным, (время соединения 7мин, время вставки 7min). Поэтому я выключаю inremental.
Я обнаружил, что дополнительные зависимости имеют a.lib И игнорировать определенные библиотеки тоже!
Итак, я удаляю его из Игнорировать определенные библиотеки, включив /incremental. время первой ссылки требуется 5 минут, но встроенное время манифеста не имеет.
Я не знаю почему, но инкрементная привязка сработала.
Я откатываюсь от всего кода проекта, поэтому я мог найти проблему в lib.
Если вы делаете все выше, вы можете попробовать мой метод. Удачи!
Ответ 15
Шаг 1 в сокращении времени сборки С++ - это больше памяти. После переключения с 4 ГБ на 12 ГБ, я видел, что мое время с привязкой всех проектов падает со скалы: с 5:50 до 1:15.