HeadlinesBriefing favicon HeadlinesBriefing.com

Buildprof визуализация времени компиляции

Hacker News •
×

Я создал buildprof (GitHub), открытый инструмент, показывающий, где уходит время при компиляции ПО в Linux. Вот видео в реальном времени, как оно профилирует чистую сборку ripgrep: смотрите демо buildprof. Иногда сборки медленные просто потому, что много кода нужно компилировать. Но чаще всего есть исправляемые проблемы: плохая параллельность, повторяющаяся работа, скачивание зависимостей или огромный вызов компилятора/линкера. buildprof делает всё это claramente видимым, чтобы вы могли увидеть, что стоит исследовать и оптимизировать. Вы запускаете его, поставив buildprof -- перед любой командой сборки, которую вы уже используете: buildprof -- make -j16, buildprof -- cargo build, buildprof -- ninja -C out/target, buildprof -- just build, buildprof -- ./dev/custom-build-script.sh. buildprof записывает каждый процесс, который запускает ваша команда сборки, включая их подпроцессы (и их подпроцессы…), и раскладывает их по временной шкале. Время движется слева направо, ширина полосы показывает длительность, а дочерние процессы появляются под тем, что их запустил. Я создал buildprof, потому что этот твит от Jarred Sumner, главного архитектора runtime Bun, жил бесплатно в моей голове: Конкретно, утверждение о том, что новая сборка Rust Bun была >5× быстрее на Linux, чем старая сборка Zig. В моем опыте проекты Zig обычно компилировались быстрее, чем проекты Rust аналогичной сложности. Это интуиция была достаточно, чтобы заставить меня почувствовать, что есть загадка для решения. Это еще больше усилили еще один важный, но легко упущенный деталь в твите: сборка Zig использовала Full LTO, а сборка Rust — Thin LTO. Компиляторы обычно оптимизируют отдельные единицы компиляции largely в изоляции. Link-time optimization (LTO) позволяет им оптимизировать через эти границы. Full LTO объединяет эти единицы в одно большое задание по оптимизации, а Thin LTO сохраняет больше разделения, поэтому большая часть работы может выполняться в paralelo. На основе прошлого опыта, это различие может иметь огромное влияние на время компиляции. Твит упомянул это вскользь, но я wondered, сколько из заявленного в заголовке улучшения на самом деле объясняет. Я начал пытаться воспроизвести цифры. Цифры воспроизводились. Но теперь что? Я взял Bun 1.3.14 и Bun 1.4.0 и написал скрипты для перезапуска их Linux x64 CI сборок на 6-ядерном, 12-потоковом Linux VM. Скрипты сохраняли шаги сборки и их зависимости, запуская всё на одной машине. Мои замеры были в том же диапазоне, что и у Jarred: Linux x64 build Zig era 30m06s, Rust era 5m37s. Моя single-machine CI-profile replay 24m24s 5m40s. Хорошо, так что разрыв появился и на моей машине. Но многое изменилось между двумя измерениями, кроме языка; так что что на самом деле было ответственным? Было ли это компилятор Zig, который тратил все это дополнительное время? Или, может быть, это Full LTO-ссылка? Или, быть может, что-то другое в сборке Bun, чего я и не думал искать? Вот здесь вступил в действие мой аналитический мозг разработчика. Обычно, когда я пытаюсь понять, почему что-то медленное, я хочу трейс: что произошло, когда это произошло и сколько времени это заняло. Было бы очень круто иметь это для этих сборок, чтобы положить их на временную шкалу и увидеть, где на самом деле ушло их время. Но сборка Involves множество разных инструментов, каждый со своим представлением о том, что происходит. Что я мог бы записать, чтобы увидеть через все они? Сборки — это деревья процессов. Когда вы запускаете cargo build или zig build, кажется, что вы запускаете одну программу. Система сборки определяет, что нужно пересобрать, порядок между этими частями и что может выполняться в paralelo. Но вообще, она не выполняет всю эту работу сама; она запускает компиляторы, генераторы кода, архивариусы, линкеры и произвольные скрипты. Эти могут запускать больше программ, которые запускают еще больше… Разные системы сборки описывают эту работу по-разному.

Cargo видит crates, Ninja видит границы сборки, а CMake генерирует инструкции для другой системы сборки. От операционной.