go tool pprof

Purpose and Scope

go tool pprof is the profiling analysis tool that ships with the Go distribution. It is the supported pprof entry point for Go users who want to inspect profiles produced by Go programs, such as CPU profiles served from an HTTP pprof endpoint or profile data stored on disk. The repository treats this command as part of the release artifact: the README in the pprof command directory says this directory is the copy of Google's pprof shipped with Go, and it distinguishes the tested Go release tool from independently installed upstream pprof binaries.

Sources: src/cmd/pprof/README, src/cmd/pprof/pprof.go

The practical consequence is that Go developers should prefer the pprof executable reached through the Go toolchain, not assume that every separately installed github.com/google/pprof version has the same compatibility properties. The README explicitly says using upstream pprof directly should work with Go programs, but the Go project only guarantees that the go tool pprof shipped with each Go release works with programs from that release. That release pairing matters when profile formats, symbolization behavior, object-file handling, or command-line behavior evolve along with the toolchain.

Sources: src/cmd/pprof/README

Relevant Source Files

  • src/cmd/pprof/README - Explains that the directory is the Go distribution copy of Google's pprof, that most implementation code is vendored from upstream, and that Go's tested support boundary is the go tool pprof shipped with a Go release.
  • src/cmd/pprof/pprof.go - Defines the command's main package, wires the vendored pprof driver into Go-specific fetch, object, and UI integrations, records telemetry counters, and implements HTTP profile fetching defaults.

System-to-Code Mapping

The command in src/cmd/pprof/pprof.go is intentionally small because most interactive analysis behavior lives behind the upstream pprof driver. Its main function opens telemetry, increments a pprof/invocations counter, constructs driver.Options, and calls driver.PProf(options). The options bind Go-specific implementations into the upstream driver: Fetch is provided by a local fetcher, Obj is provided by a local object tool, and UI is created by newUI. This arrangement lets the Go distribution reuse the upstream pprof command model while inserting Go toolchain behavior where profile retrieval, object inspection, or user interaction must match Go releases.

Sources: src/cmd/pprof/pprof.go

The README explains why this shape can look more abstract than a Go-only profiler might need. Pprof is used inside Google for C++, Java, and Go programs, and the abstractions were retained so updates can be shared between the Go repository's vendored copy and Google's broader pprof implementation. The file even warns contributors not to treat the level of abstraction in this program as a style example for their own Go programs. For repository readers, that note is important: the command is a compatibility wrapper around a multi-language profiling engine, not a minimal idiomatic sample application.

Sources: src/cmd/pprof/README

Supported Profiling Workflow

A typical Go workflow begins with a profile source and invokes the bundled command through the Go toolchain. The source can be a local profile file or an HTTP endpoint exposed by a running program. The fetcher.Fetch implementation first checks whether the provided source string names an existing file on disk. If it does, the function returns control to the regular pprof path rather than trying to interpret the string as a network location. This protects file names containing colons, such as timestamped profile names, from being misparsed as malformed URLs.

Sources: src/cmd/pprof/pprof.go

When the source is not an existing file, the command applies Go-specific URL handling before handing the profile to the driver. The fetcher calls adjustURL, prints that it is fetching a profile over HTTP, optionally tells the user to wait for the requested duration, and then calls getProfile. This source-backed flow explains why go tool pprof can accept compact endpoint-like arguments while still supporting plain local files. It also explains why network fetch behavior belongs in the command wrapper rather than in user code that merely records profiles.

Sources: src/cmd/pprof/pprof.go

The Go-specific HTTP default is the CPU profile endpoint. The command declares cpuProfileHandler as /debug/pprof/profile, and adjustURL uses that path when the parsed source URL has no path or only /. In other words, a host and port can be enough to mean the standard Go CPU profile handler. Duration and timeout values are also applied at this URL-adjustment boundary, so the user-facing profiling session is converted into a concrete request before the upstream profile parser is invoked.

Sources: src/cmd/pprof/pprof.go

API Components and Runtime Behavior

The compact public contract of this command is the executable entry point exposed as go tool pprof; inside the repository, its concrete source-level entry points are main, fetcher.Fetch, getProfile, statusCodeError, adjustURL, and the cpuProfileHandler constant. main is responsible for invoking the upstream driver. fetcher.Fetch decides whether to delegate local file handling or perform Go-specific HTTP fetch setup. getProfile performs the HTTP request and parses the response body as a pprof profile through the upstream profile.Parse API.

Sources: src/cmd/pprof/pprof.go

getProfile also shows the supported transport behavior visible in the wrapper. It parses the source URL, recognizes the special https+insecure scheme by installing a TLS configuration with certificate verification skipped, rewrites the scheme to https, and constructs an HTTP client. That client uses proxy settings from the environment and sets ResponseHeaderTimeout to the requested timeout plus five seconds. These details matter when diagnosing fetch failures: an endpoint can be local or remote, proxy configuration can participate, and timeout behavior is controlled before parsing begins.

Sources: src/cmd/pprof/pprof.go

Error reporting has a Go pprof endpoint special case. If the HTTP response is not 200 OK, statusCodeError checks for an X-Go-Pprof header and a text response body. When those are present, it reads the body and includes both the HTTP status and endpoint-provided text in the error message. Otherwise it reports the server response status. This behavior makes command-line failures more useful when the server-side pprof handler intentionally returns a diagnostic message rather than a binary profile.

Sources: src/cmd/pprof/pprof.go

Implementation Constraints and Contributor Notes

The Go repository's pprof command is not a fork to freely redesign in isolation. The README says the bulk of the code is vendored from github.com/google/pprof, and pprof.go asks contributors to consider upstreaming modifications to those packages. That means local changes should be limited to Go distribution integration points unless there is a reason to carry a Go-specific delta. The command wrapper is where Go-specific defaults, telemetry, object-file integration, and release compatibility expectations are concentrated.

Sources: src/cmd/pprof/README, src/cmd/pprof/pprof.go

Telemetry is part of the command's startup path. main calls counter.Open, increments pprof/invocations, and after the pprof driver returns counts command flags under the pprof/flag: prefix. The code also exits with status 2 after printing an error to standard error when the driver reports failure. Those details are small but useful for maintainers because they define the observable command lifecycle: initialize counting, run the pprof driver, record flag usage, and convert an error into a process failure.

Sources: src/cmd/pprof/pprof.go

Next Steps

Use this page when you need to understand the supported Go pprof entry point or when you are reviewing a change near src/cmd/pprof. For user-facing profiling tasks, start with go tool pprof from the same Go release that built or runs the target program, then provide either a local profile file or an HTTP source exposing the standard pprof handler. For implementation work, keep the boundary clear: Go-specific behavior belongs in the wrapper, while broad pprof engine changes should be considered for upstream first.