Профилирование Makefile - PullRequest
       9

Профилирование Makefile

19 голосов
/ 23 марта 2011

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

Я вижу некоторые пути для оптимизации -

  • Сокращение количества раз, когда Makefile анализируется и DAG пересчитывается из-за включения фрагмента Makefile.
  • Сокращениечисло обращений к внешнему Makefile с make -C
  • Сокращение расширений переменных
  • и т. д.

- однако сначала я хочу узнать, где мои узкие места,Поскольку оптимизация без профилирования - это пустая трата жизни, я хочу спросить: Как профилировать Makefile?

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

... и просто для вытеснения некоторых возможных ответов.Я знаю, что могут быть более быстрые и лучшие системы сборки, чем GNU make - (Лично я с нетерпением жду, чтобы увидеть, что люди CMake придумают в отношении системы Ninja), - но, к сожалению, замена системы сборки отсутствует в картах.

Ответы [ 7 ]

3 голосов
/ 23 марта 2011

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

  • -q (вопрос) заставит его просто решить, что должно быть сделано, ничего не делать, ничего не печатать, но вернуть код состояния выхода, указывающий, нужно ли что-либо делать.Вы можете просто рассчитать время для любой цели, которая вас интересует (включая «все»).
  • -n (no-op) будет печатать рецепты, а не выполнять их.Наблюдение за их прокруткой даст вам общее представление о том, как Make тратит свое время, и, если хотите, вы можете делать хитрые уловки, чтобы рассчитать время процесса.
  • -t (touch) заставит его коснуться целевых файлов, которые необходимо восстановить, вместо того, чтобы фактически восстанавливать их.Затем скрипт может посмотреть на время обновления файлов, найти большие пробелы и сказать вам, какие цели требуют большой продуманности.

РЕДАКТИРОВАТЬ:

Я НЕПРАВИЛЬНО.

Make создает DAG и решает, какие цели должны быть восстановлены, прежде чем он восстанавливает любую из них.Поэтому, как только он начинает выполнять правила, печатать рецепты или трогать файлы, часть интересующей нас работы заканчивается, и наблюдаемое время бесполезно. Так что параметры -n и -t не годятся, но -q все еще полезен как грубый инструмент.Также -d расскажет вам мыслительный процесс Марка;он не скажет вам время, но он укажет, какие цели требуют много шагов для рассмотрения.

2 голосов
/ 23 марта 2011

Я не думаю, что есть какой-либо способ профилировать сами Makefiles.

Вы могли бы что-то сделать, однако: для нулевой сборки (все обновлено) запустите make верхнего уровня в strace -tt -fv и посмотрите, какие части дерева, какие рекурсивные субмаки, какие обращения к файлам и т. Д. Происходят неожиданно длинный.

Вычисляемые переменные (var := $(shell ...)), повторные вызовы файла NFS stat и т. Д. Часто делают make медленным.

1 голос
/ 30 мая 2015

Было несколько попыток добавить профилирование в GNU make. См. Например https://github.com/eddyp/make-profiler

Моя недавняя попытка проникновения в эту область заключалась в расширении римейка для вывода информации с использованием формата valgrind callgrind ; тогда для визуализации можно использовать kcachegrind или gprof2dot . Прямо сейчас проверьте ветку профилирования в github . Или посмотрите этот kcachegrind скриншот .

Это все еще в стадии разработки, любая помощь будет оценена. Помощь может заключаться в том, как лучше запечатлеть вещи & mdash; там много информации & mdash; или как лучше записать его в формате callgrind, а также улучшить то, что код C выполняет при профилировании. Так что вам не обязательно быть программистом Си, чтобы помочь.

1 голос
/ 24 марта 2011

Это зависит от того, что вы пытаетесь измерить, и от того, насколько сложны ваши Makefile.

Если вы просто хотите измерить анализ, вызовите тривиальную цель без зависимостей.Но это не очень хорошо работает, если у вас есть целевые правила (например, из-за использования $(eval)).

, если вы также хотите измерить процесс вывода (который я считаю гораздо быстрее) Iне вижу способа вызвать make для достижения этой цели.

Если вы также хотите включить разветвление оболочки, которая выполняет команды, все снова становится легко: установите $(SHELL) на то, что окружаетфактическое выполнение команды оболочки с информацией о времени.

Другая идея состоит в том, чтобы запустить сам исходный код make под профилировщиком или добавить сообщения о времени.

1 голос
/ 23 марта 2011

Это работа, но я бы взял источник Make, собрал его с отладочной информацией и запустил под gdb и случайной паузой во время ожиданияЭто.Это показало бы, что он делает и почему.Вероятно, было бы необходимо взглянуть не только на стек вызовов, но и на внутреннюю структуру данных, поскольку Make является интерпретатором.Поскольку Make называет себя подчиненным приложением, это может усложнить работу.Мне нужно было бы выяснить, как отлаживать подчиненный вызов.

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

И не беспокойтесь об уровне оптимизации - узкие места, вероятно, намного больше этого.

0 голосов
/ 24 марта 2011

Make не занимает много времени, разбирая Makefile и собирая DAG. Я использовал make-файлы, которые $(eval...) тысячи строк make, создавали даг со многими сотнями файлов и возвращались почти мгновенно (ну ладно, через секунду или две), когда нечего делать.

Так куда движется ваша скорость?

  • Рекурсивный make (т.е. запуск другого make в рецепте оболочки (${MAKE} blah...)) всегда медленный. (Это тоже всегда плохо ИМХО.)
  • Вы должны отказаться от использования $(shell...) & mdash; Используйте make изготовления, где это возможно
  • Ваши Make-файлы должны работать правильно при использовании с -jn (n> 1). Убедитесь, что вы говорите, чтобы сделать именно то, что может быть построено параллельно с чем. Не используйте петли оболочки, если это вообще возможно.
0 голосов
/ 24 марта 2011

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

Одно предупреждение. Опция -d заставляет make выдавать непристойный объем продукции. Вы обязательно захотите перенаправить вывод в файл. Ваш терминал поблагодарит вас позже.

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

...