DEV Community

nabsei
nabsei

Posted on • Edited on

buildline: Merging Cargo and Ninja's Build Profiling into One Timeline

Core Problem

Build tools operate in isolated silos with their own profiling systems. Cargo's --timings and Ninja's logs each show their own performance, but neither reveals the gaps between tools, like the 2.7-second delay before cargo starts after ninja finishes. These inter-tool delays often represent the actual bottlenecks in CI builds but remain invisible to all existing profilers.

The Solution

Buildline merges profiling data from multiple build tools into a single Chrome Trace Event Format timeline, viewable in Perfetto without custom UI development. Rather than using process interception, it wraps each tool invocation individually:

BUILDLINE_SESSION=./build.trace buildline -- ninja
BUILDLINE_SESSION=./build.trace buildline -- cargo build
# open build.trace in https://ui.perfetto.dev
Enter fullscreen mode Exit fullscreen mode

Each wrapper stamps the wall-clock time before executing the tool, reads its profiling artifacts afterward, and appends normalized data to the shared trace file. No orchestration layer is required.

Design Architecture

The Span structure captures build events with relative timestamps, not wall-clock, which lets adapters stay pure functions producing deterministic output suitable for golden-file testing. The wrapper layer alone handles wall-clock offsetting.

Category enforcement uses a closed enum rather than free-form strings. This prevents one adapter from emitting "compile" while another uses "Compile," keeping the merged timeline coherent instead of silently incoherent.

Status variants include "Incomplete" for spans that never finished, which matters for identifying where builds hung or were terminated.

Contribution Model

Adding support for new build systems (Bazel, Gradle, MSBuild) requires only a fixture pair: a real trace artifact and its expected normalized JSON output. CI validates adapters automatically, without a subjective code review.

Current Status

Currently supports Ninja and Cargo, both with golden-file test coverage. Single-machine only for now; distributed builds are out of scope until there's a real answer for clock synchronization. One documented fragility: Cargo's --timings has no stable JSON output, so buildline reads embedded HTML data that could change without notice.

Update (Aug 4): added a fair bit since this went up.

  • A webpack adapter (--profile --json), same golden-file testing as ninja/cargo.
  • A generic adapter for anything that already writes Chrome Trace Event Format on its own, no dedicated adapter needed. Tested it against real captures from tsc --generateTrace and Bazel's --profile, which stress it in opposite ways: tsc streams begin/end pairs with real nesting, Bazel writes complete events and never even names its own process. Both fixtures are in the repo.
  • CONTRIBUTING.md, since the CLI's error message pointed at a file that didn't exist for two weeks.

Still ninja, cargo, and webpack as dedicated adapters, plus the generic path for anything else. Install/repo links unchanged.

Installation: cargo install buildline
Repository: https://github.com/nabsei/buildline
Crate: https://crates.io/crates/buildline

Top comments (0)