PGO and the uncommitted profile
June 21, 2026 · View on GitHub
Go's profile-guided optimization (PGO) reads a pprof CPU
profile at compile time. Since Go 1.21, go build
automatically uses a default.pgo file in the main package
directory. The compiler then favors the recorded hot paths:
it inlines hot functions past the normal budget,
devirtualizes interface calls that mostly hit one concrete
type, and lays out hot code together.
Why the profile is not committed
Committing cmd/mdsmith/default.pgo would make every plain
go build profile-guided. But the file is a binary pprof
snapshot. Two branches that both refresh it always conflict,
and no byte-level merge is meaningful. A take-current merge
driver was tried and rejected. The managed .gitattributes
block and mdsmith merge-driver install are product
features. They run in users' repositories and must never
carry entries that only fit mdsmith's own repository.
The path is gitignored so a locally generated profile cannot be committed by accident. On this workload PGO measured within noise (~0-2%), so plain builds lose nothing user-visible.
How the release build gets a profile
The release workflow generates the profile inside the
pipeline. So the published binaries are profile-guided
without a tracked artifact. release.yml runs a pgo job
after preflight and before the build matrix. The job builds
mdsmith-release and runs mdsmith-release pgo /tmp/mdsmith-pgo.
That subcommand:
- Builds the
mdsmithbinary. - Builds the two benchmark corpora using the same plumbing
as
mdsmith-release bench:corpus_repofrom the repo's tracked Markdown,corpus_neutralfrom the pinned Rust Book and Reference. - Records a CPU profile over each corpus in both the
default and
mado-parity(bench-parity.mdsmith.yml) configurations viaMDSMITH_CPUPROFILE— four runs total. - Merges the four runs with
go tool pprof -protointocmd/mdsmith/default.pgo.
The pgo job uploads that file as the pgo-profile artifact.
Each build matrix job downloads it to cmd/mdsmith/ and
prints the profile size before running go build. Go finds
cmd/mdsmith/default.pgo in the main package directory
automatically — no flag needed. The file is never committed.
The benchmark harness deliberately does not build with this profile (see the benchmark page). The published numbers measure the plain, reproducible build, not the PGO-optimized release output.
Generating a profile locally
The release pgo job's logic is also a local command. From
the repo root, mdsmith-release pgo [workdir] runs the whole
recipe below — build, corpora, four profiled check runs,
merge — and writes cmd/mdsmith/default.pgo for you; the
workdir defaults to /tmp/mdsmith-bench.
For experiments, the equivalent shell records the real workload — both benchmark corpora, both configurations — and merges the runs. Staleness is safe: samples that match no function are ignored, so an old profile cannot break a build; it just helps less.
# Corpora as built by the benchmark harness (run.sh /
# mdsmith-release bench) under its workdir:
W=/tmp/mdsmith-bench
P=docs/research/benchmarks/bench-parity.mdsmith.yml
go build -o "$W/mdsmith" ./cmd/mdsmith
for c in corpus_repo corpus_neutral; do
MDSMITH_CPUPROFILE="$W/full-$c.prof" \
"$W/mdsmith" check "$W/$c" || true
MDSMITH_CPUPROFILE="$W/parity-$c.prof" \
"$W/mdsmith" check -c "$P" "$W/$c" || true
done
go tool pprof -proto -output=cmd/mdsmith/default.pgo \
"$W/mdsmith" "$W"/*.prof
Rebuild after writing the file; go build picks it up from
cmd/mdsmith/ automatically. PGO never changes behavior —
tests, output, and rule results are identical with or
without it.