Profile-Guided Optimization
Purpose and Scope
Profile-guided optimization, or PGO, is the workflow of collecting execution profiles from a representative run and using those profiles to guide later optimization decisions. In the Go project, the public reader-facing workflow is normally centered on the go command, compiled programs, and pprof-compatible profiles. The source evidence for this page grounds the profile side of that workflow: how pprof accepts profile sources, how it turns profiles into reports, and what an instrumentable command-line workload looks like when it uses cancellation, timeouts, and controlled resource limits.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go, src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go, src/database/sql/example_cli_test.go
The key reader problem is not merely “how do I run a faster build,” but “how do I produce and inspect a profile that is credible enough to guide optimization.” A profile is only useful when it comes from a workload that resembles the production path being optimized. The database example in the standard library tests demonstrates several important properties of such a workload: it accepts explicit command-line inputs, validates those inputs, opens a database handle, configures the connection pool, observes process cancellation, and bounds operations with contexts and timeouts. Those traits make the run repeatable and help keep profile data from being dominated by setup accidents or hung operations.
Sources: src/database/sql/example_cli_test.go
The vendored pprof driver is the repository-backed profile analysis surface. Its CLI parser defines a source model with fields for profile inputs, executable name, build ID, base profiles, diff-base comparison, normalization, duration, timeout, symbolization mode, HTTP UI settings, comments, and frame-retention behavior. That structure is important for PGO because optimization feedback is only as good as the mapping between sampled profile data and the executable or symbols being analyzed. The driver also exposes report commands such as annotated source, annotated assembly, graphs, raw profile output, tags, and top entries.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go, src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go
Relevant Source Files
- src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go — Defines pprof report commands, command metadata, help text generation, extension hooks, and the built-in report formats used to inspect profile data.
- src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go — Parses pprof command-line flags into a profile source description, including profile sources, executable metadata, base comparisons, symbolization, duration, timeout, and web UI options.
- src/database/sql/example_cli_test.go — Provides a concrete command-line program shape with flags, environment-derived DSN, connection-pool configuration, cancellation, timeouts, and a parameterized query; it is a useful model for building repeatable workloads before collecting profiles.
System-to-Code Mapping
The pprof driver separates two concerns that are often blended together in casual profiling workflows. The first concern is source selection: where the profile comes from, what executable or build ID should be associated with it, whether there are base profiles for subtraction or comparison, and whether a dynamic profile should be collected for a number of seconds. The second concern is report generation: once the profile is loaded, a command chooses a view such as text, raw, list, disasm, or dot. This separation matters for PGO because a profile should be prepared and verified before it is trusted as optimization feedback.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go, src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go
In the CLI source model, Sources names the profile inputs, ExecName names the executable, and BuildID can override the first mapping’s build identifier. Base, DiffBase, and Normalize describe comparison-oriented analysis. Seconds and Timeout cover dynamic profile collection, while Symbolize, AllFrames, and Comment affect how profile frames and annotations are interpreted. The HTTP fields, HTTPHostport and HTTPDisableBrowser, support interactive viewing. These names are not generic documentation terms; they are concrete fields in the pprof driver’s source type.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go
The command registry in commands.go maps user-visible command names to report formats, optional post-processing, optional visualization, parameter expectations, one-line descriptions, and usage text. Commands that accept a regular expression parameter, such as source or assembly listing commands, are represented differently from commands that simply emit a report. This is why pprof can expose both -text-style report selection and parameterized commands such as matching functions for annotated listings. For PGO triage, those focused reports help identify whether profile weight is concentrated in code that the developer expected to optimize.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go
The database CLI example shows the other side of the mapping: the profiled program should define a stable unit of work. Example_openDBCLI reads id and dsn flags, rejects missing required values, opens a database/sql handle with sql.Open, configures connection limits with SetConnMaxLifetime, SetMaxIdleConns, and SetMaxOpenConns, then creates a cancellable root context. A signal handler cancels that context on interrupt, and the program performs a bounded Ping followed by a bounded Query. This shape gives profile collection a clear beginning, useful steady work, and an orderly cancellation path.
Sources: src/database/sql/example_cli_test.go
Execution Flow
A practical PGO preparation flow starts by choosing the workload and making sure it can be run repeatedly. The database example uses explicit flags instead of hidden constants, which lets the operator select a representative record ID and data source at runtime. It also treats missing configuration as fatal before useful work starts. That is important for profile collection because failed setup can still produce a profile, but the samples would describe error handling or initialization rather than the target workload. Good PGO inputs come from successful, realistic execution, not from profiles accidentally collected from misconfigured runs.
Sources: src/database/sql/example_cli_test.go
After the program has a credible workload, the next step is to collect or provide a pprof-compatible profile and inspect it. The pprof CLI requires at least one profile source; when no source is specified, parsing returns an error. If more than one argument is present, the parser attempts to recognize the first argument as an executable or build ID override by opening it through the object tooling. That behavior reflects a core profiling requirement: sampled addresses are far more useful when the tool can connect them to the binary and symbols that produced them.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go
Once the profile source and executable metadata are established, the user chooses a report. A quick first pass might use text or top to find the heaviest entries. A deeper pass might use list to show annotated source for matching functions, or disasm to show assembly listings annotated with samples. If graph analysis is useful, dot produces DOT output, and the HTTP mode can present an interactive web UI. If the profile needs to be inspected without interpretation, raw, comments, and tags expose lower-level profile metadata.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go, src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go
Comparisons are especially useful when evaluating optimization feedback. The pprof CLI includes base for profile subtraction and diff_base for comparison against a base profile, along with normalization controls. In a PGO workflow, this lets a developer compare a candidate workload profile with another profile from a previous run, another binary, or a control scenario. The code evidence here does not define the compiler’s optimization decisions, but it does show that the profiling toolchain supports the comparison operations developers need before deciding whether a profile is representative enough to feed into build-time optimization.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go
API Components and Compact Reference
The pprof command implementation is extensible. AddCommand(cmd string, format int, post PostProcessor, desc, usage string) adds or replaces a command in the pprof command set. SetVariableDefault(variable, value string) changes a pprof variable default through the configuration mechanism. PostProcessor is a function type that accepts an input reader, output writer, and plugin UI, returning an error. These extension points are useful for specialized visualization or report handling, although the default built-in commands already cover common PGO triage tasks.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go
The built-in report command set includes comments, disasm, dot, list, peek, raw, tags, text, and top in the supplied source. Their descriptions show the intended analysis modes: comments output profile comments, disassembly annotates assembly with samples, DOT emits graph format, list annotates source for matching functions, peek shows callers and callees for matching functions, raw prints the raw profile representation, tags lists profile tags, and text or top output ranked textual entries. Commands with hasParam collect a regular expression parameter from the CLI.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go
The CLI flags in the supplied parser are also concrete enough to serve as a reference checklist. Source and comparison flags include -diff_base, -base, -symbolize, -buildid, -timeout, -add_comment, and -all_frames. CPU collection uses -seconds. Heap display selectors include -inuse_space, -inuse_objects, -alloc_space, and -alloc_objects. Contention selectors include -total_delay, -contentions, and -mean_delay. Tool and UI controls include -tools, -http, and -no_browser. Report command flags are installed dynamically from the command registry.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go, src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go
The workload example’s public API usage is equally concrete. It uses flag.Int64, flag.String, and flag.Parse for CLI inputs, os.Getenv for a DSN default, sql.Open to construct the database handle, and pool.Close for cleanup. It configures pooling with SetConnMaxLifetime, SetMaxIdleConns, and SetMaxOpenConns. It creates contexts with context.WithCancel and context.WithTimeout, verifies connectivity with PingContext, and performs a parameterized lookup with QueryRowContext and sql.Named. These are reliable building blocks for profiling a real command rather than a synthetic micro-snippet.
Sources: src/database/sql/example_cli_test.go
Implementation Details and Constraints
A profile used for optimization should be repeatable, symbolizable, and attributable. Repeatability comes from a stable command-line workload and bounded operations. Symbolization comes from giving pprof enough executable or build ID information to map samples to code. Attribution comes from choosing report formats that connect samples to functions, source, assembly, tags, and comments. The supplied pprof driver and SQL example together demonstrate those constraints even though they live in different areas of the tree: one is the analysis tool, and the other is a model of application code that can be profiled.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go, src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go, src/database/sql/example_cli_test.go
Context cancellation is a subtle but important profiling detail. The database example cancels the root context on interrupt and uses one-second and five-second timeouts for ping and query operations. Without those bounds, profile collection can be skewed by long waits, connection stalls, or manual termination at inconsistent points. In PGO preparation, the same principle applies broadly: the run should end for a known reason after a representative amount of work. A profile dominated by startup, shutdown, or timeout behavior may still be accurate, but it may not guide the desired optimization target.
Sources: src/database/sql/example_cli_test.go
The pprof parser’s -seconds and -timeout flags represent another operational boundary. Dynamic profiles need a duration, and remote or generated profile fetching needs a timeout. The -add_comment option allows free-form annotations to be recorded with the profile, which is useful when tracking which workload, input data, binary, or experiment produced a profile. The -all_frames and symbolization options help control frame handling, which can affect whether important call paths are visible in reports. These options belong in the preparation checklist before a profile becomes a build input.
Sources: src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go
Practical Next Steps
To prepare a profile for optimization work, first make the target command explicit and repeatable. Model it after the standard-library CLI example: validate flags, fail early on missing configuration, set resource limits deliberately, wire cancellation, and put timeouts around external work. Then collect a pprof-compatible profile from a representative run and open it with the pprof tooling. Start with top or text, inspect important functions with list or disasm, use tags and comments to verify provenance, and compare with base or diff_base when evaluating changes.
Sources: src/database/sql/example_cli_test.go, src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go, src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go
After the profile has been checked, continue to the go command and compiler architecture material for the build-time side of PGO. This page intentionally focuses on the profile preparation and inspection layer grounded by the supplied repository files. Read it alongside toolchain command documentation when you need invocation details, diagnostics documentation when you need broader profiling and tracing context, and compiler architecture documentation when you need to understand where optimization decisions are implemented.