Как заставить Windows работать так же быстро, как Linux для компиляции C++?

Я знаю, что это не столько вопрос программирования, но он актуален.

Я работаю над довольно крупным кроссплатформенным проектом. В Windows я использую VC++ 2008. В Linux я использую gcc. В проекте около 40 тыс. Файлов. Windows компилирует и связывает один и тот же проект в 10–40 раз медленнее, чем Linux. Как я могу это исправить?

Инкрементная сборка одного изменения - 20 секунд для Linux и> 3 минуты для Windows. Зачем? Я даже могу установить компоновщик 'gold' в Linux и сократить это время до 7 секунд.

Аналогично, git в 10–40 раз быстрее в Linux, чем в Windows.

В git-случае возможно, что git использует не Windows оптимальным образом, а VC++? Вы могли бы подумать, что Microsoft захочет сделать своих собственных разработчиков максимально продуктивными, и более быстрая компиляция будет иметь большое значение для этого. Может быть, они пытаются поощрить разработчиков в C#?

Как простой тест, найдите папку с множеством подпапок и выполните простую

dir /s > c:\list.txt

на винде. Сделайте это дважды и время второго запуска, чтобы он запускался из кэша. Скопируйте файлы в Linux и сделайте эквивалентные 2 прогона и время второго прогона.

ls -R > /tmp/list.txt

У меня есть 2 рабочие станции с точно такими же характеристиками. HP Z600s с 12 ГБ оперативной памяти, 8 ядер на 3,0 ГГц. Для папки с ~400k файлами Windows занимает 40 секунд, Linux занимает < 1 секунду.

Могу ли я установить параметры реестра для ускорения работы Windows? Что дает?


Несколько слегка релевантных ссылок, относящихся ко времени компиляции, не обязательно ввода / вывода.

13 ответов

Если не придет хардкорный системный хакер Windows, вы не получите больше, чем партизанские комментарии (что я не буду делать) и спекуляции (что я и собираюсь попробовать).

  1. Файловая система - вы должны попробовать те же операции (включая dir) в той же файловой системе. Я сталкивался с этим, который сравнивает несколько файловых систем для различных параметров.

  2. Кэширование. Однажды я попытался запустить компиляцию в Linux на RAM-диске и обнаружил, что это медленнее, чем запуск на диске благодаря тому, как ядро ​​заботится о кэшировании. Это хороший аргумент в пользу Linux и может быть причиной того, что производительность настолько различна.

  3. Неверные спецификации зависимостей в Windows. Может быть, спецификации зависимости хрома для Windows не так корректны, как для Linux. Это может привести к ненужным компиляциям, когда вы вносите небольшие изменения. Вы можете проверить это, используя ту же цепочку инструментов компилятора в Windows.

Несколько идей:

  1. Отключить 8.3 имен. Это может иметь большое значение для дисков с большим количеством файлов и относительно небольшим количеством папок: fsutil behavior set disable8dot3 1
  2. Используйте больше папок. По моему опыту, NTFS начинает замедляться с более чем 1000 файлов в папке.
  3. Включить параллельные сборки с MSBuild; просто добавьте ключ "/m", и он автоматически запустит одну копию MSBuild на ядро ​​процессора.
  4. Поместите ваши файлы на SSD - очень помогает при случайном вводе / выводе.
  5. Если ваш средний размер файла намного превышает 4 КБ, рассмотрите возможность перестройки файловой системы с большим размером кластера, который приблизительно соответствует вашему среднему размеру файла.
  6. Убедитесь, что файлы были дефрагментированы. Фрагментированные файлы приводят к большому количеству обращений к диску, что может увеличить пропускную способность в 40 и более раз. Используйте утилиту "contig" от sysinternals или встроенный дефрагментатор Windows.
  7. Если ваш средний размер файла небольшой, а раздел, на котором вы находитесь, относительно полон, возможно, вы работаете с фрагментированным MFT, что плохо сказывается на производительности. Кроме того, файлы размером менее 1 КБ хранятся непосредственно в MFT. Упомянутая выше утилита "contig" может помочь, или вам может потребоваться увеличить размер MFT. Следующая команда удвоит его до 25% объема: fsutil behavior set mftzone 2 Измените последнее число на 3 или 4, чтобы увеличить размер на 12,5%. После выполнения команды перезагрузите компьютер и создайте файловую систему.
  8. Отключить время последнего доступа: fsutil behavior set disablelastaccess 1
  9. Отключить службу индексирования
  10. Отключите антивирусное и антишпионское программное обеспечение или, по крайней мере, установите соответствующие папки, которые будут игнорироваться.
  11. Поместите свои файлы на физический диск, отличный от операционной системы и файла подкачки. Использование отдельного физического диска позволяет Windows использовать параллельные операции ввода-вывода для обоих дисков.
  12. Посмотрите на флаги вашего компилятора. Компилятор Windows C++ имеет множество опций; убедитесь, что вы используете только те, которые вам действительно нужны.
  13. Попробуйте увеличить объем памяти, который ОС использует для буферов в выгружаемом пуле (сначала убедитесь, что у вас достаточно ОЗУ): fsutil behavior set memoryusage 2
  14. Проверьте журнал ошибок Windows, чтобы убедиться, что у вас нет случайных ошибок на диске.
  15. Посмотрите на счетчики производительности, связанные с физическим диском, чтобы увидеть, насколько заняты ваши диски. Большая длина очереди или длительное время на передачу - плохие признаки.
  16. Первые 30% дисковых разделов намного быстрее, чем остальная часть диска с точки зрения времени сырой передачи. Узкие разделы также помогают минимизировать время поиска.
  17. Вы используете RAID? Если это так, вам может потребоваться оптимизировать ваш выбор типа RAID (RAID-5 плох для операций с интенсивной записью, таких как компиляция)
  18. Отключите все службы, которые вам не нужны
  19. Дефрагментация папок: копирование всех файлов на другой диск (только файлы), удаление исходных файлов, копирование всех папок на другой диск (только пустые папки), затем удаление исходных папок, дефрагментация исходного диска, сначала копирование структуры папок, а затем скопируйте файлы. Когда Windows создает большие папки по одному файлу за раз, папки оказываются фрагментированными и медленными. (здесь также должен помочь "contig")
  20. Если вы связаны с вводом / выводом и у вас есть запасные циклы ЦП, попробуйте включить сжатие диска. Он может обеспечить значительное ускорение для файлов с высокой степенью сжатия (например, исходного кода), с некоторыми затратами на ЦП.

NTFS всегда экономит время доступа к файлам. Вы можете попробовать отключить его: "fsutil поведенческий набор disablelastaccess 1" (перезапуск)

Насколько я могу судить, проблема с Visual C++ заключается в том, что для команды компиляторов не является приоритетом оптимизация этого сценария. Их решение заключается в том, что вы используете их предварительно скомпилированную функцию заголовка. Это то, что сделали конкретные проекты Windows. Это не портативный, но работает.

Кроме того, в Windows у вас обычно есть антивирусные сканеры, а также инструменты восстановления системы и поиска, которые могут полностью испортить время сборки, если они контролируют вашу папку buid за вас. Windows 7 Resouce Monitor может помочь вам определить это. У меня есть ответ с некоторыми дополнительными советами по оптимизации времени сборки vC++, если вы действительно заинтересованы.

Сложность в этом заключается из-за того, что C++ имеет тенденцию распространяться и сам процесс компиляции по многим маленьким, отдельным файлам. В Linux это хорошо, а в Windows нет. Если вы хотите создать действительно быстрый компилятор C++ для Windows, постарайтесь сохранить все в оперативной памяти и как можно меньше касаться файловой системы.

Таким же образом вы создадите более быструю цепочку компиляции Linux C++, но это менее важно в Linux, потому что файловая система уже выполняет большую часть этой настройки для вас.

Причина этого кроется в культуре Unix: исторически производительность файловой системы была гораздо более высоким приоритетом в мире Unix, чем в Windows. Нельзя сказать, что это не было приоритетом в Windows, просто в Unix это был более высокий приоритет.

  1. Доступ к исходному коду.

    Вы не можете изменить то, что не можете контролировать. Отсутствие доступа к исходному коду Windows NTFS означает, что большинство усилий по повышению производительности были сделаны с помощью аппаратных улучшений. То есть, если производительность низкая, вы решаете проблему, улучшая аппаратное обеспечение: шину, носитель данных и т. Д. Вы можете сделать так много, только если вам нужно обойти проблему, но не решить ее.

    Доступ к исходному коду Unix (даже до открытого кода) был более распространенным. Поэтому, если вы хотите повысить производительность, вы должны сначала обратиться к ней с программным обеспечением (дешевле и проще), а затем с аппаратным обеспечением.

    В результате многие люди в мире получили докторскую степень, изучая файловую систему Unix и находя новые способы повышения производительности.

  2. Unix стремится к множеству маленьких файлов; Windows стремится к нескольким (или одному) большому файлу.

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

    В результате Unix имеет высоко оптимизированные системные вызовы для открытия и закрытия файлов, сканирования каталогов и так далее. История исследований Unix охватывает десятилетия оптимизации файловой системы, в которой много внимания уделялось улучшению доступа к каталогам (поиск и полное сканирование каталогов), открытию начальных файлов и так далее.

    Приложения Windows, как правило, открывают один большой файл, держат его открытым в течение долгого времени, закрывают, когда все готово. Подумайте о MS-Word. msword.exe (или что-то еще) открывает файл один раз и добавляет в течение нескольких часов, обновляет внутренние блоки и так далее. Значение оптимизации открытия файла будет потрачено впустую время.

    История бенчмаркинга и оптимизации Windows была связана с тем, насколько быстро можно читать или записывать длинные файлы. Вот что оптимизируется.

    К сожалению, разработка программного обеспечения имеет тенденцию к первой ситуации. Черт, лучшая система обработки текста для Unix (TeX/LaTeX) предлагает вам поместить каждую главу в отдельный файл и #include их все вместе.

  3. Unix ориентирован на высокую производительность; Windows ориентирована на пользовательский опыт

    Unix запущен в серверной комнате: нет пользовательского интерфейса. Единственное, что видят пользователи, это скорость. Поэтому скорость является приоритетом.

    Windows запустилась на рабочем столе: пользователи заботятся только о том, что они видят, и они видят пользовательский интерфейс. Поэтому на улучшение пользовательского интерфейса тратится больше энергии, чем на производительность.

  4. Экосистема Windows зависит от планового устаревания. Зачем оптимизировать программное обеспечение, если до нового оборудования всего год или два?

    Я не верю в теории заговора, но если бы я это сделал, я бы отметил, что в культуре Windows меньше стимулов для повышения производительности. Бизнес-модели Windows зависят от людей, покупающих новые машины, такие как часы. (Вот почему цена акций тысяч компаний будет затронута, если MS выпустит операционную систему с опозданием или если Intel пропустит дату выпуска чипа.) Это означает, что есть стимул решать проблемы с производительностью, говоря людям покупать новое оборудование; не путем улучшения реальной проблемы: медленные операционные системы. Unix происходит из научных кругов, где бюджет ограничен, и вы можете получить докторскую степень, придумав новый способ сделать файловые системы быстрее; редко кто-то в академии получает очки за решение проблемы путем выдачи заказа на покупку. В Windows нет никакого заговора с целью замедлить работу программного обеспечения, но вся экосистема зависит от запланированного устаревания.

    Кроме того, поскольку Unix является открытым исходным кодом (даже когда его не было, у всех был доступ к источнику), любой скучающий аспирант может прочитать код и стать известным, сделав его лучше. Этого не происходит в Windows (у MS есть программа, которая предоставляет ученым доступ к исходному коду Windows, им редко пользуются). Посмотрите на этот список работ, связанных с Unix: http://www.eecs.harvard.edu/margo/papers/ или посмотрите историю работ Остерхауса, Генри Спенсера или других. Черт возьми, одним из самых больших (и наиболее приятных для просмотра) дебатов в истории Unix были споры между Остерхаусом и Селцером http://www.eecs.harvard.edu/margo/papers/usenix95-lfs/supplement/rebuttal.html мире Windows такого не происходит. Вы можете видеть, как поставщики сталкиваются друг с другом, но в последнее время это кажется гораздо более редким явлением, так как инновации, похоже, достигают уровня стандартов.

Вот как я это вижу.

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

Я лично обнаружил, что при запуске виртуальной машины с Windows в Linux удалось устранить большую часть медленных операций ввода-вывода в Windows, вероятно потому, что linux vm выполнял много операций кэширования, чем сама Windows.

Благодаря этому я смог ускорить время компиляции большого (250Kloc) C++ проекта, над которым я работал, с 15 минут до 6 минут.

Инкрементное связывание

Если решение VC 2008 настроено как несколько проектов с выходами.lib, необходимо установить "Использовать входы зависимостей библиотеки"; это делает ссылку компоновщиком непосредственно на файлы.obj, а не на.lib. (И фактически делает это постепенно ссылка.)

Производительность обхода каталога

Немного несправедливо сравнивать обход каталога на исходном компьютере с обходом вновь созданного каталога с теми же файлами на другом компьютере. Если вам нужен эквивалентный тест, вам, вероятно, следует сделать еще одну копию каталога на исходном компьютере. (Это может все еще быть медленным, но это может быть связано с любым количеством вещей: фрагментация диска, короткие имена файлов, фоновые службы и т. Д.) Хотя я думаю, что проблемы с dir /s больше связаны с записью вывода, чем с измерением фактической производительности обхода файла. Четное dir /s /b > nul работает медленно на моей машине с огромным каталогом.

Я уверен, что это связано с файловой системой. Я работаю над кроссплатформенным проектом для Linux и Windows, где весь код является общим, за исключением тех случаев, когда код, зависящий от платформы, абсолютно необходим. Мы используем Mercurial, а не git, поэтому "Linuxness" git не применяется. Внесение изменений из центрального репозитория в Windows занимает больше времени, чем в Linux, но я должен сказать, что наши машины с Windows 7 работают намного лучше, чем машины с Windows XP. Компиляция кода после этого еще хуже на VS 2008. Это не просто hg; CMake работает намного медленнее и в Windows, и оба эти инструмента используют файловую систему больше, чем что-либо еще.

Проблема настолько серьезна, что большинство наших разработчиков, работающих в среде Windows, даже не утруждают себя выполнением инкрементных сборок - они обнаруживают, что вместо этого создание единой сборки происходит быстрее.

Кстати, если вы хотите значительно увеличить скорость компиляции в Windows, я бы предложил вышеупомянутую сборку единства. Правильно реализовать это в системе сборки (я сделал это для нашей команды в CMake), но однажды все сделано автоматически, что ускоряет работу наших серверов непрерывной интеграции. В зависимости от того, сколько двоичных файлов выдает ваша система сборки, вы можете получить от 1 до 2 порядков улучшения. Ваш пробег может отличаться. В нашем случае я думаю, что он ускорил сборку Linux в три раза, а сборку Windows - примерно в 10 раз, но у нас есть много общих библиотек и исполняемых файлов (что уменьшает преимущества единой сборки).

Как вы строите свой большой кроссплатформенный проект? Если вы используете общие make-файлы для Linux и Windows, вы можете легко снизить производительность Windows в 10 раз, если make-файлы не предназначены для быстрой работы в Windows.

Я только что исправил некоторые make-файлы кроссплатформенного проекта, используя общие (GNU) make-файлы для Linux и Windows. Make начинает sh.exe процесс для каждой строки рецепта, вызывающий разницу в производительности между Windows и Linux!

Согласно ГНУ составьте документацию

.ONESHELL:

должен решить проблему, но эта функция (в настоящее время) не поддерживается для Windows make. Поэтому переписывание рецептов в одну логическую строку (например, путем добавления;\ или \ в конце текущих строк редактора) сработало очень хорошо!

ИМХО, это все о производительности дискового ввода-вывода. Порядок величины предполагает, что многие операции выполняются на диске под Windows, тогда как в Linux они обрабатываются в памяти, то есть Linux лучше кешируется. Лучшим вариантом под Windows будет переместить ваши файлы на быстрый диск, сервер или файловую систему. Подумайте о покупке твердотельного диска или о переносе файлов на виртуальный диск или быстрый NFS-сервер.

Я выполнил тесты обхода каталогов, и результаты очень близки к отчетным временам компиляции, предполагая, что это не имеет никакого отношения ко времени обработки ЦП или алгоритмам компилятора / компоновщика.

Измеренные времена, как указано выше, обходят дерево каталогов хрома:

  • Windows Home Premium 7 (8 ГБ ОЗУ) в NTFS: 32 секунды
  • Ubuntu 11.04 Linux (2 ГБ ОЗУ) в NTFS: 10 секунд
  • Ubuntu 11.04 Linux (2 ГБ ОЗУ) на ext4: 0,6 секунды

Для тестов я вытащил источники хрома (оба под win/linux)

git clone http://github.com/chromium/chromium.git 
cd chromium
git checkout remotes/origin/trunk 

Чтобы измерить время, которое я побежал

ls -lR > ../list.txt ; time ls -lR > ../list.txt # bash
dir -Recurse > ../list.txt ; (measure-command { dir -Recurse > ../list.txt }).TotalSeconds  #Powershell

Я отключил временные метки доступа, мой антивирусный сканер и увеличил настройки диспетчера кэша в Windows (>2 ГБ ОЗУ) - и все это без каких-либо заметных улучшений. Дело в том, что из коробки Linux работала в 50 раз лучше, чем Windows с четвертью оперативной памяти.

Для любого, кто хочет утверждать, что цифры неправильные - по любой причине - пожалуйста, попробуйте и опубликуйте свои результаты.

Попробуйте использовать Jom вместо Nmake

Получите это здесь: http://qt.gitorious.org/qt-labs/jom

Дело в том, что nmake использует только одно из ваших ядер, jom - это клон nmake, использующий многоядерные процессоры.

GNU make делает это "из коробки" благодаря опции -j, которая может быть причиной его скорости по сравнению с Microsoft nmake.

jom работает, выполняя параллельно разные команды make на разных процессорах / ядрах. Попробуйте почувствовать разницу!

Я хочу добавить только одно наблюдение, используя Gnu make и другие инструменты из инструментов MinGW в Windows: кажется, они разрешают имена хостов, даже когда инструменты не могут даже общаться по IP. Я предполагаю, что это вызвано некоторой процедурой инициализации среды выполнения MinGW. Запуск локального прокси-сервера DNS помог мне улучшить скорость компиляции с помощью этих инструментов.

Раньше у меня сильно болела голова, потому что скорость сборки снизилась примерно в 10 раз, когда я параллельно открыл VPN-соединение. В этом случае все эти поиски DNS проходили через VPN.

Это наблюдение может также относиться к другим инструментам сборки, не только на основе MinGW, и оно могло бы измениться в последней версии MinGW.

Недавно я мог заархивировать другой способ ускорить компиляцию примерно на 10% в Windows, используя Gnu make, заменив mingw bash.exe версией из win-bash

(Win-bash не очень удобен в отношении интерактивного редактирования.)

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