Подтвердить что ты не робот

Как оптимизировать время запуска SCons script?

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

scons: Building targets ...

шаг.

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

Команда 'scons --max-drift = 1 --implicit-deps-unchanged' выполнит вашу сборку как можно быстрее.

ИЛИ

  • env.Decider('MD5-timestamp'): с 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/С++ #includes), что может быть дорогостоящим процессом. Вы можете сообщить SCons о кешировании неявных зависимостей между вызовами, используя -implicit-deps-unchanged. Используя эти параметры, вы обещаете SCons, что вы не изменили ни одну из неявных зависимостей с момента последнего запуска. Если вы измените неявные зависимости, то использование -implicit-deps-changed приведет к их повторному сканированию и кэшированию. (Вы не можете установить этот параметр из файлов SConstruct или SConscript.)
  • - неявный кеш: эта опция сообщает SCons интеллектуально кэшировать неявные зависимости. Он пытается определить, изменились ли неявные зависимости со времени последней сборки, и если да, то они будут пересчитывать их. Это обычно медленнее, чем использование -implicit-deps-неизменным, но также более точным. Вместо указания этого в командной строке каждого запуска вы можете установить эту опцию в свой файл SConstruct или SConscript, используя "SetOption (" implicit_cache ", 1)".
  • CPPPATH: обычно вы сообщаете Scons о включенных каталогах, устанавливая переменную построения CPPPATH, которая заставляет SCons искать эти каталоги при выполнении неявных зависимостей, а также включает в себя эти каталоги в командной строке компиляции. Если у вас есть файлы заголовков, которые никогда или редко меняются (например, заголовки систем или заголовки времени выполнения C), вы можете исключить их из CPPPATH и включить их в конструктивную переменную CCFLAGS, что приводит к тому, что SCons игнорирует те, которые включают каталоги при сканировании для неявных зависимостей. Тщательная настройка включенных каталогов таким образом может привести к резкому увеличению скорости с очень небольшой потерей точности.
  • Избегайте сканирования RCS и SCCS с помощью env.SourceCode( ".", None) - это особенно интересно, если вы используете большое количество заголовков 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

Ответ 3

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

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

env.Decider('timestamp-newer')

Там также MD5-timestamp, которая сначала проверит метку времени, а затем сравните содержимое с использованием Md5, если оно действительно изменилось, если метка времени более новая.

env.Decider('MD5-timestamp')

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

scons -j 2

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

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

Ответ 4

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

Ответ 5

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

DefaultEnvironment(tools=[])

Ответ 6

Добавьте в свой SConscript что-то вроде

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

и запустите с помощью --debug=explain. Вы увидите, что Scons тратит время на оценку