A minimal Go service showcasing how to set up runtime profiling using net/http/pprof
and visualize metrics like heap usage, goroutines, and garbage collection using Statsviz. Includes a liveness endpoint and tools to simulate load.
- Go 1.18+
- A terminal with
curl
or any HTTP request tool
Clone the repo:
git clone https://github.com/gradientsearch/go-service-profiling.git
cd go-service-profiling
Download dependencies:
go mod tidy
Start the service:
go run main.go
This starts the server on http://localhost:3010.
You can simulate a burst of traffic using:
hey -n 1000 -c 100 http://localhost:3010/liveness
Using profiling tools helps identify potential issues like memory leaks, unexpected goroutine growth, or inefficient GC cycles.
-
A stable heap graph generally indicates healthy memory management.
-
Spikes during traffic bursts are expected, but consistent growth may require investigation.
- net/http/pprof
- Statsviz
- hey (for load testing)
To stop the server, just hit Ctrl+C.
Do not expose the debug endpoints to the public or production environments. The profiling endpoints provided by the net/http/pprof
package expose sensitive runtime information that could potentially be used for malicious purposes, including heap dumps, goroutine stacks, and other performance data. These endpoints should be restricted to trusted internal users or disabled in production.
To avoid exposing these endpoints, you can:
- Bind the server to
localhost
or an internal network interface. - Use environment variables or build tags to conditionally include profiling in development environments only.
- Protect the endpoints with authentication or access control mechanisms (e.g., basic auth or IP whitelisting).
Be cautious when running this in a production environment and always ensure these endpoints are not publicly accessible.
Metric | Description |
---|---|
Heap in use | Memory occupied by live objects and dead objects not yet freed by the GC: /memory/classes/heap/objects + /memory/classes/heap/unused . |
Heap free | Memory that could be returned to the OS but hasn't been: /memory/classes/heap/free . |
Heap released | Memory that has been returned to the OS: /memory/classes/heap/free . |
Heap sys | Estimate of all heap memory obtained from the OS: /memory/classes/heap/objects + unused + released + free . |
Heap objects | Memory used by live and not-yet-freed objects: /memory/classes/heap/objects . |
Heap stacks | Memory used for stack space: /memory/classes/heap/stacks . |
Heap goal | Heap size target for the end of the GC cycle: gc/heap/goal . |
Live objects | Number of live or unswept objects occupying heap memory: /gc/heap/objects . |
Live bytes | Currently allocated bytes (not yet GC’ed): /gc/heap/allocs - /gc/heap/frees . |
Mspan in-use | Memory used by active mspan structures: /memory/classes/metadata/mspan/inuse . |
Mspan free | Reserved but unused memory for mspan : /memory/classes/metadata/mspan/free . |
Mcache in-use | Memory used by active mcache structures: /memory/classes/metadata/mcache/inuse . |
Mcache free | Reserved but unused memory for mcache : /memory/classes/metadata/mcache/free . |
Goroutines | Count of live goroutines: /sched/goroutines . |
Events per second | Total number of goroutine scheduling events, from /sched/latencies:seconds , multiplied by 8. |
Events per second per P | Events per second divided by GOMAXPROCS : /sched/gomaxprocs:threads . |
OS stacks | Stack memory allocated by the OS: /memory/classes/os-stacks . |
Other | Memory for trace buffers, debugging structures, finalizers, and more: /memory/classes/other . |
Profiling buckets | Memory used by profiling stack trace hash map: /memory/classes/profiling/buckets . |
Total | Total memory mapped by the Go runtime: /memory/classes/total . |
Mark assist | CPU time goroutines spent helping the GC: /cpu/classes/gc/mark/assist . |
Mark dedicated | CPU time on dedicated processors for GC tasks: /cpu/classes/gc/mark/dedicated . |
Mark idle | CPU time for GC tasks using otherwise idle CPU: /cpu/classes/gc/mark/idle . |
Pause | Total CPU time the app was paused by the GC: /cpu/classes/gc/pause . |
GC total | Total CPU time spent doing GC: /cpu/classes/gc/total . |
Mutex wait | Time goroutines spent blocked on a sync.Mutex or sync.RWMutex : /sync/mutex/wait/total . |
Scannable globals | Amount of scannable global variable space: /gc/scan/globals . |
Scannable heap | Amount of scannable heap space: /gc/scan/heap . |
Scanned stack | Bytes of stack scanned during the last GC cycle: /gc/scan/stack . |