Статьи

Построить, почему вы идете медленно?

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

Чтобы опробовать инструменты профилирования Bazel, создайте свою любимую (или, скорее, наименее любимую) цель с --profileопцией:

$ bazel build --profile=myprofile.out //snail:slow-lib

Это запишет профиль в файл myprofile.out в текущем каталоге. Как только ваша сборка завершится, вы сможете взглянуть на этот файл, но он не предназначен для чтения людьми. Вместо этого подключите его к analyze-profileкоманде Базеля :

$ bazel analyze-profile --html myprofile.out

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

Название изображения

Сделайте ваш проект быстрее, чем этот.

(После того, как я сделал это фото, я переместил улитку на траву, так как я почти уверен, что ей не очень приятно находиться посреди тротуара в Нью-Йорке.)

Дин, анализ, вероятно, сделано. Теперь вы можете открыть myprofile.out.html и увидеть свою сборку, разбитую на сотни или тысячи отдельных шагов. Скриншот вывода:

Снимок экрана 2015-09-18 в 2.51.55 вечера

Я загрузил HTML-страницу, чтобы вы могли увидеть все здесь и поиграть с ней (она откроется в новой вкладке).

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

Диаграмма показывает, что все 200 потоков сборки делали во время сборки в любой момент времени (один поток на строку). Сборка разделена на несколько «фаз», которые показаны в виде разноцветных столбцов на графике:

  1. Первые 1,5 секунды (темно-серые) были потрачены на инициализацию команды сборки, а это означает, что она просто разбирает параметры и настраивает кэш.
  2. Следующая ~ 1 секунда (зеленая) была этапом загрузки, на котором Bazel выясняет, какие пакеты ему понадобятся, загружает внешние зависимости, а также находит и анализирует файлы BUILD.
  3. Следующими ~ 100 мс (полоска светло-серого цвета) была фаза анализа зависимостей, на которой Базель выяснила, какие зависимости были кешированы и очищены, и поэтому их не нужно перестраивать.
  4. Наконец, Базель перешел в фазу сборки (розовый фон), фактически собрав все, что нужно было построить.

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

Ниже графика есть раздел «Фаза выполнения». «Выполнение» может быть немного запутанным в этом контексте: оно относится к выполнению сборки, а не к запуску вашей программы. Фаза выполнения отображается в розовую фазу на приведенной выше диаграмме. В этом разделе есть подраздел «Критический путь», который разбивает то, что ожидала ваша сборка:

Critical path (13.339 s):
    Id        Time Percentage   Description
  6722     48.1 ms    0.36%   Zipaligning apk
  6721      344 ms    2.58%   Generating signed apk
  6720      540 ms    4.05%   Converting bazel-out/local_darwin-fastbuild/bin/android/android_deploy.jar to dex format
  6719      230 ms    1.73%   Building deploy jar android/android_deploy.jar
  6718     1.051 s    7.88%   Building android/libandroid.jar (0 files)
  6717     15.7 ms    0.12%   Extracting interface //android activities
  6716     1.744 s   13.07%   Building android/libactivities.jar (1 files)
  6715      785 ms    5.89%   Processing resources
  6712     3.737 s   28.01%   Building external/default_android_tools/src/tools/android/java/com/google/devtools/build/android/libandroid_builder_lib.jar (17 files) [for host]
  6711     4.843 s   36.30%   Writing file external/default_android_tools/src/tools/android/java/com/google/devtools/build/android/libandroid_builder_lib.jar-2.params [for host]
           1.73 ms    0.01%   [2 middleman actions]

Как видите, сборка была «заблокирована» более чем на 8 секунд при сборке libandroid_builder_lib.jar и его файла параметров. К счастью, эти файлы не должны меняться между сборками (если вы не обновите свой Android SDK, что не должно происходить между каждой сборкой). Если я внесу изменения в libactivities.jar (собственно ядро ​​программы) и пересоберу, я получу:

$ bazel build --profile profile2 //android
INFO: Writing profile data to '/Users/kchodorow/gitroot/examples/tutorial/profile2'
INFO: Found 1 target...
INFO: From Generating unsigned apk:

THIS TOOL IS DEPRECATED. See --help for more information.

INFO: From Generating signed apk:

THIS TOOL IS DEPRECATED. See --help for more information.

Target //android:android up-to-date:
  bazel-bin/android/android_deploy.jar
  bazel-bin/android/android_unsigned.apk
  bazel-bin/android/android.apk
INFO: Elapsed time: 4.545s, Critical Path: 2.72s

Вот новая страница профиля для этой инкрементной сборки.

Обратите внимание, что критический путь составляет всего 2,718 секунды, а не 13,339! Если мы посмотрим на профиль, то увидим, что новый критический путь гораздо более изящен:

Critical path (2.718 s):
    Id        Time Percentage   Description
   543     52.3 ms    1.92%   Zipaligning apk
   542      342 ms   12.59%   Generating signed apk
   541      577 ms   21.22%   Converting bazel-out/local_darwin-fastbuild/bin/android/android_deploy.jar to dex format
   540      245 ms    9.00%   Building deploy jar android/android_deploy.jar
   539     1.502 s   55.26%   Building android/libactivities.jar (1 files)

Сейчас сборка libactivities.jar является самой тяжелой операцией на критическом пути, поэтому мы могли бы решить эту проблему, разбив ее на отдельные библиотеки, которые не нужно перекомпилировать каждый раз, когда что-то меняется.

Профили, создаваемые Bazel, могут быть … плотными … поэтому не стесняйтесь спрашивать в списке рассылки, если вам нужна помощь в их интерпретации. Также, если вас интересует больше по теме, ознакомьтесь с документацией по профилированию .