profile

A simple Go library that wraps runtime/pprof and fgprof to enable CPU, memory, mutex, block, or trace profiling with a single deferred call.

Library
Go
vv1.7.0
2,058stars
BSD-2-Clause

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity0
Maintenance20
Community60
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
72/100Good
Architecture72
Code Quality72
Innovation80
Learning Curve65

pkg/profile is a small Go package built around one idea: profiling your application should take a single line of code. Wrapping defer profile.Start().Stop() at the top of main transparently enables CPU profiling, writes the resulting pprof file to a temp directory, and cleans it up when the deferred Stop() runs — no manual os.Create, pprof.StartCPUProfile, or file-handle bookkeeping required.

Beyond the default CPU mode, the package exposes functional-options helpers — MemProfile, MemProfileHeap, MemProfileAllocs, MutexProfile, BlockProfile, TraceProfile, ThreadcreationProfile, GoroutineProfile, and ClockProfile (backed by github.com/felixge/fgprof for wall-clock profiling) — each swapping in the matching runtime/pprof, runtime/trace, or fgprof call and the correct output filename. ProfilePath and NoShutdownHook give callers control over where files land and whether a SIGINT handler should flush profiles automatically, which matters for programs with their own signal handling.

Internally the package guards against double-starts with an atomic flag, and each mode’s Stop behavior is captured as a closure so callers never need to know which underlying pprof API was used. It has shipped largely unchanged since 2014 and is still commonly reached for when someone wants ad hoc profiling without wiring up net/http/pprof or hand-rolling file management.

What You Get

  • One-line CPU profiling via defer profile.Start().Stop() with automatic temp-file management
  • Memory profiling in either heap or allocs mode, with a configurable sampling rate
  • Mutex, block, thread-creation, and goroutine profiling modes, each mapped to the matching runtime/pprof lookup
  • Execution tracing via runtime/trace, and wall-clock profiling via the bundled fgprof dependency
  • A SIGINT shutdown hook that stops and flushes an in-progress profile automatically (optional, via NoShutdownHook)
  • Configurable output directory via ProfilePath instead of the default ioutil.TempDir

Common Use Cases

  • Dropping a single deferred call into a CLI tool’s main to capture a CPU profile for a one-off performance investigation
  • Comparing heap allocation behavior between two implementations by toggling MemProfileHeap vs MemProfileAllocs
  • Diagnosing lock contention in a concurrent service with MutexProfile or BlockProfile without adding a pprof HTTP endpoint
  • Capturing an execution trace (TraceProfile) to inspect goroutine scheduling and GC pauses in go tool trace
  • Profiling short-lived batch or worker processes where wiring up net/http/pprof isn’t practical

Under The Hood

Architecture The entire package lives in one file, profile.go, organized around a Profile struct configured through the functional-options pattern: exported option funcs like CPUProfile, MemProfile, and ProfilePath mutate a Profile value before Start runs a single switch over prof.mode to wire up the correct runtime/pprof, runtime/trace, or fgprof call and capture its teardown logic in a closer closure. An atomic started flag prevents overlapping profiling sessions, and an optional background goroutine listens for SIGINT to call Stop and exit cleanly. There’s no layering beyond this because the package solves one narrow, self-contained problem: nothing else would break if it changed since it exposes only Start/Stop and its option functions.

Tech Stack Written for Go 1.13 with no external dependencies beyond github.com/felixge/fgprof (used only for the wall-clock/ClockProfile mode); everything else — CPU, memory, mutex, block, thread-creation, goroutine, and trace profiling — is handled through the standard library’s runtime/pprof, runtime/trace, runtime, and os/signal packages. There’s no build tooling beyond go build/go test, and CI is a now-defunct Travis config, reflecting the project’s age and stability rather than active tooling investment.

Code Quality The package is well tested for its size: profile_test.go runs table-driven integration tests that compile and execute small Go programs as subprocesses and assert on their stdout/stderr, exercising each profiling mode end to end rather than only unit-testing internals, and example_test.go documents usage as runnable Go examples. Error handling in the library itself favors fail-fast log.Fatalf calls on unrecoverable setup errors (e.g. failing to create a profile output file), which is appropriate for a profiling helper invoked at process startup. There’s no dedicated linter config, but every exported identifier carries a GoDoc comment.

API Design The package’s whole value proposition is ergonomics: enabling profiling is a single deferred call, and switching profiling modes is a matter of passing a different named option function with a consistent XProfile naming convention. Documentation is thorough at the GoDoc level, and the functional-options pattern lets new profiling modes and settings (like MemProfileRate) compose without breaking the zero-argument default case, keeping the API surface small even as capabilities were added over the years.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search