2009-08-23 2 views
20

У меня есть сценарий SCons, который занимает около 10 секунд, чтобы узнать, что ничего не нужно перестраивать, что ужасно долго для того, что по сути является довольно небольшим проектом. Чтение сам SConscript занимает всего второй или два, большую часть времени проводят на:Как оптимизировать время запуска скрипта SCons?

scons: Building targets ... 

шаг.

Как я могу узнать, что именно делает scons? И какой другой общий совет можно дать при написании сценариев быстрого сценария?

ответ

8

ли немного проб и ошибок, чтобы выяснить, почему SCons медленно, некоторые результаты до сих пор (точные результаты, конечно, варьируются в зависимости от структуры и сложности сценария Scons):

  • CacheDir() имеет нет заметного негативного воздействия.
  • Decider() оказывает незначительное воздействие, не стоит беспокоиться.
  • Использование variant_dir/VariantDir() увеличивает время сборки примерно на 10%.
  • Чтение файла SConstruct занимает около 10% от общего количества звонков.
  • Наибольшее воздействие, похоже, связано с библиотечными зависимостями, поскольку Gtkmm в проекте удвоил время сборки для меня.

Возможные решения:

  • Не делать полные перестроение, но только перестраивать каталог/модуля вы работаете (scons -u вместо scons -D).
  • Сделайте части SConscript необязательными, поэтому его можно восстановить только при ручном вызове.
  • Используйте флаг -isystem компилятор для библиотеки включает в себя вместо -I, это изменение в одиночку обрушил время сборки из 10.5sec в 6sec для меня, это может быть легко достигнуто с небольшим количеством SED вызова:

    env.ParseConfig('pkg-config --cflags --libs gtkmm-2.4 | sed "s/-I/-isystem/g"')

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

Использование CacheDir() и scons -j N, конечно, также очень рекомендую, но только ускоряет фактически здание, а не оценку самого сценария Scons.

+12

В SCons не используется средство проверки зависимостей GCC, оно имеет собственный набор регулярных выражений на основе Python для поиска. Использование -системы выполняется быстрее, потому что вы скрываете все эти заголовки от SCons. Если какой-либо из этих заголовков изменится, SCons не может сказать. Что вы делаете, это, по сути, отбраковка большого блока DAG, представленного неявными зависимостями (заголовками). Это ускоряет шаг прохождения за счет правильности. – BenG

9

scons md5-sums файлы, чтобы выяснить, что они изменили, так что это в значительной степени md5sums все ваши файлы.

Вы можете сказать ему, чтобы использовать только временные метки, чтобы решить, что нужно перестроить и не использовать MD5sum все файлы каждый раз, как «make», что должно ускорить процесс. Это может быть более хрупким. например если файл был изменен в течение 1 секунды в последний раз, когда он был построен, счёты не заметят этого. Используйте

env.Decider('timestamp-newer') 

Там также MD5-метка времени, которая будет проверять метку времени, а затем сравнить содержимое с помощью md5, если он на самом деле изменилось, если временная метка новее.

env.Decider('MD5-timestamp') 

Еще один простой способ ускорить работу - запустить параллельное здание с использованием параметра -j.

scons -j 2 

На моей 2-сердечной коробке -j 3 обычно дает наибольшее ускорение.

Некоторые данные о том, что делают scons, могут быть сделаны с аргументом --debug для вызова scons, см. Справочную страницу для различных опций.

+2

Я играл с Decider(), но он имеет близкое к нулю воздействие на время сборки (т. Е. В диапазоне 0,1 сек). Я тоже уже «scons -j 2», но это помогает только самой сборке, а не обработке зависимостей, эта часть, похоже, использует только одно ядро. – Grumbel

+0

Нужно ли устанавливать Дешифратор в каждом файле SConscript или только в исходном файле SConstruct, чтобы использовать его во всей сборке? –

+0

Достаточно верхнего файла SConstruct. (хотя если вы каким-то образом создадите отдельные среды где-то еще, которые не скопированы/клонированы из среды, где вы вызываете Decider(), вам нужно снова вызвать ее для этой среды. - Если вы не создаете экземпляры каких-либо сред, просто позвоните Decider() вместо env.Decider()) – nos

25

(Stolen непосредственно из http://www.scons.org/wiki/GoFastButton)

Команды 'SCons --max дрейф = 1 --implicit-Deps-неизменный' выполнит свой билд как можно быстрее.

ИЛИ:

  • env.Decider ('MD5-временной метки'): по состоянию на SCons 0,98, вы можете установить функцию Decider на окружающую среду. MD5-timestamp говорит, что если отметка времени совпадает, не беспокойтесь о повторном MD5-файле. Это может привести к огромным ускорениям. См. Справочную страницу для информации.
  • --max-drift: По умолчанию SCons будет вычислять контрольную сумму MD5 каждого исходного файла в вашей сборке при каждом запуске и будет кэшировать контрольную сумму только после того, как файл будет 2 дня. Это значение по умолчанию составляет 2 дня, чтобы защитить от перекоса часов от NFS или систем контроля версий. Вы можете настроить эту задержку с помощью --max-drift = SECONDS, где SECONDS - некоторое количество секунд. Уменьшение SECONDS может улучшить скорость сборки за счет исключения излишних контрольных сумм MD5. Вместо указания этого в командной строке каждого запуска вы можете установить эту опцию внутри вашего файла SConstruct или SConscript, используя «SetOption (« max_drift », SECONDS)».
  • --implicit-deps-unchanged: По умолчанию SCons сканирует все исходные файлы для неявных зависимостей (например, заголовок C/C++ #includes), что может быть дорогостоящим процессом. Вы можете сообщить SCons о кешировании неявных зависимостей между вызовами, используя -implicit-deps-unchanged. Используя эти параметры, вы обещаете SCons, что вы не изменили ни одну из неявных зависимостей с момента последнего запуска. Если вы измените неявные зависимости, то использование -implicit-deps-changed приведет к их повторному сканированию и кэшированию. (Вы не можете установить эту опцию из файлов SConstruct или SConscript.)
  • --imbleicit cache: Этот параметр сообщает SCons интеллектуально кэшировать неявные зависимости. Он пытается определить, изменились ли неявные зависимости со времени последней сборки, и если да, то они будут пересчитывать их. Это обычно медленнее, чем использование -implicit-deps-неизменным, но также более точным. Вместо указания этого в командной строке каждого запуска вы можете установить эту опцию в свой файл SConstruct или SConscript, используя «SetOption (« implicit_cache », 1)».
  • CPPPATH: обычно вы сообщаете Scons о включенных каталогах, задавая переменную конструкции CPPPATH, которая заставляет SCons искать эти каталоги при выполнении неявных зависимостей, а также включает в себя эти каталоги в командной строке компиляции. Если у вас есть файлы заголовков, которые никогда или редко меняются (например, заголовки систем или заголовки времени выполнения C), вы можете исключить их из CPPPATH и включить их в конструктивную переменную CCFLAGS, что приводит к тому, что SCons игнорирует те, которые включают каталоги при сканировании для неявных зависимостей. Тщательная настройка включенных каталогов таким образом может привести к резкому увеличению скорости с очень небольшой потерей точности.
  • Избегайте сканирования RCS и SCCS с помощью env.SourceCode (".", None) - это особенно интересно, если вы используете множество заголовков c или C++ в своей программе и что ваша файловая система удалена (nfs, samba) ,
  • При использовании «BuildDir» используйте его с «duplicate», равным 0: «BuildDir (dir1, dir2, duplicate = 0». Это заставит scons вызывать Builders, используя имена путей исходных файлов в src_dir и путь имена производных файлов в файле build_dir.Однако это может вызвать проблемы с сборкой, если исходные файлы генерируются во время сборки, если любые вызываемые инструменты жестко закодированы, чтобы поместить производные файлы в тот же каталог, что и исходные файлы.
  • На мульти -процессорной машине может быть полезно запустить сразу несколько заданий - используйте -jobs N (где N - количество процессоров на вашем компьютере) или «SetOption (« num_jobs », N)» внутри вашего SConstruct или SConscript. На машинах Windows число процессоров доступно в переменной среды «NUMBER_OF_PROCESSORS».
  • Если у вас имеется более нескольких десятков препроцессоров («-DFOO1 -DFOO2»), вы можете найти из использования --profile, что SCons проводит много времени в функции subst(), обычно просто добавляя строку -D к определяет снова и снова. Это может реально замедлить сборку, где ничего не изменилось. При настройке 100+ я видел сокращение времени создания без ничего с 35 до 20 с использованием идеи, описанной в разделе «Кэширование CPPDEFINES» в другом месте на этой странице.

Еще один трюк, позволяющий ускорить работу, заключается в том, чтобы избежать повторных программ, когда общая библиотека была изменена, но не перестроена. См. SharedLibrarySignatureOverride

5

Когда SCons создает первый Environment, он проводит серию поисков, чтобы узнать, какие инструменты доступны. Вы можете избежать ненужных проверок и ускорений SCons, явно выбрав инструменты в DefaultEnvironment, прежде чем создавать свой первый env.

DefaultEnvironment(tools=[]) 
7

Перемещение стороннего участника из CPPPATH и в CCFLAGS имеет огромное значение. Для нашего проекта с 12 внешними включенными каталогами (включая boost и python), ничего не делать, компиляция прошла с 30 с до 3 с - 10-кратное ускорение.

+1

Тот же опыт для меня. Пути Boost в CPPPATH просто взрывают дерево зависимостей по многим причинам.Есть что-то о boost libs, который его вызывает. Возможно, из-за большого количества файлов .hpp. –

2

добавить на SConscript что-то вроде

if 'explain' in GetOption("debug"): 
    Progress('Evaluating $TARGET\n') 

и работать с --debug=explain. Вы увидите, что SCons проводит время, оценивая

Смежные вопросы