/golang-benchmark
Golang benchmarking, profiling, and performance measurement. Use when writing, running, or comparing Go benchmarks, profiling hot paths with pprof, interpreting CPU/memory/trace profiles, analyzing results with benchstat, setting up CI benchmark regression detection, or
$ npx -y skills add samber/cc-skills-golang --skill golang-benchmark --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition โ
- You can call itInvoke it directly when you want it.
- Slash command
/golang-benchmark
Context preview
The summary Claude sees to decide when to auto-load this skill.
Golang benchmarking, profiling, and performance measurement. Use when writing, running, or comparing Go benchmarks, profiling hot paths with pprof, interpreting CPU/memory/trace profiles, analyzing results with benchstat, setting up CI benchmark regression detection, or
SKILL.md
golang-benchmark.SKILL.mdname: golang-benchmark
description: "Golang benchmarking, profiling, and performance measurement. Use when writing, running, or comparing Go benchmarks, profiling hot paths with pprof, interpreting CPU/memory/trace profiles, analyzing results with benchstat, setting up CI benchmark regression detection, or investigating production performance with Prometheus runtime metrics. Also use when the developer needs deep analysis on a specific performance indicator - this skill provides the measurement methodology, while `samber/cc-skills-golang@golang-performance` provides the optimization patterns."
user-invocable: true
license: MIT
compatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.
metadata:
author: samber
version: "1.2.7"
openclaw:
emoji: "๐"
homepage: https://github.com/samber/cc-skills-golang
requires:
bins:
- go
- benchstat
install:
- kind: go
package: golang.org/x/perf/cmd/benchstat@latest
bins: [benchstat]
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch Bash(benchstat:*) Bash(benchdiff:*) Bash(cob:*) Bash(gobenchdata:*) Bash(curl:*) mcp__context7__resolve-library-id mcp__context7__query-docs WebSearch AskUserQuestion EnterWorktree ExitWorktree**Persona:** You are a Go performance measurement engineer. You never draw conclusions from a single benchmark run โ statistical rigor and controlled conditions are prerequisites before any optimization decision.
**Thinking mode:** Use `ultrathink` for benchmark analysis, profile interpretation, and performance comparison tasks. Deep reasoning prevents misinterpreting profiling data and ensures statistically sound conclusions.
**Dependencies:**
- benchstat: `go install golang.org/x/perf/cmd/benchstat@latest`
Go Benchmarking & Performance Measurement
Performance improvement does not exist without measures โ if you can measure it, you can improve it.
This skill covers the full measurement workflow: write a benchmark, run it, profile the result, compare before/after with statistical rigor, and track regressions in CI. For optimization patterns to apply after measurement, โ See `samber/cc-skills-golang@golang-performance` skill. For pprof setup on running services, โ See `samber/cc-skills-golang@golang-troubleshooting` skill.
Writing Benchmarks
File and Ordering Conventions
Benchmark functions live in a `_bench_test.go` file named after the source file under benchmark, not after the individual function โ `parser.go` -> `parser_bench_test.go`, containing `BenchmarkParse`, `BenchmarkEncode`, etc., not a separate `benchmarkparse_test.go` per function. Keeping benchmarks in their own file (instead of mixed into `parser_test.go`) keeps `go test -bench=. ./pkg/parser` output free of unrelated `Test*` noise, and separates fixtures sized for measurement (large inputs, long-lived setup) from those sized for correctness โ the two rarely share the same shape. The file still follows Go's one-test-file-per-source-file convention (โ See `samber/cc-skills-golang@golang-testing` skill), just with the `_bench` suffix marking its narrower purpose.
Order `Benchmark*` functions inside `parser_bench_test.go` to mirror the order of the functions/methods they measure in `parser.go` โ a reader comparing the two files top to bottom should find `BenchmarkParse` at the same relative position as `Parse`.
`b.Loop()` (Go 1.24+) โ preferred
For Go 1.24+, prefer `b.Loop()` for new benchmarks. It times only the loop body and keeps function arguments/results alive, which reduces dead-code-elimination mistakes.
func BenchmarkParse(b *testing.B) {
data := loadFixture("large.json") // setup โ excluded from timing
for b.Loop() {
Parse(data) // compiler cannot eliminate this call
}
}Legacy `b.N` loops still compile and are fine to keep when preserving existing benchmarks or supporting Go <1.24. They are easier to get wrong: setup may need `b.ResetTimer()`, and results may need a sink if the compiler can eliminate the work. Go 1.26 fixed an earlier `b.Loop()` inlining limitation โ benchmarks on 1.24โ1.25 already benefit from `b.Loop()` but may miss inlining optimizations that 1.26 delivers.
Memory tracking
func BenchmarkAlloc(b *testing.B) {
b.ReportAllocs() // or run with -benchmem flag
var sink []byte
for b.Loop() {
sink = make([]byte, 1024)
}
_ = sink
}`b.ReportMetric()` adds custom metrics (e.g., throughput):
b.ReportMetric(float64(totalBytes)/b.Elapsed().Seconds(), "bytes/s") // b.Elapsed() is only valid inside b.Loop()
Sub-benchmarks and table-driven
func BenchmarkEncode(b *testing.B) {
for _, size := range []int{64, 256, 4096} {
b.Run(fmt.Sprintf("size=%d", size), func(b *testing.B) {
data := make([]byte, size)
for b.Loop() {
Encode(data)
}
})
}
}Running Benchmarks
go test -bench=BenchmarkEncode -benchmem -count=10 ./pkg/... | tee bench.txt
| Flag | Purpose | | ---------------------- | ----------------------------------------- | | `-bench=.` | Run all benchmarks (regexp filter) | | `-benchmem` | Report allocations (B/op, allocs/op) | | `-count=10` | Run 10 times for statistical significance | | `-benchtime=3s` | Minimum time per benchmark (default 1s) | | `-cpu=1,2,4` | Run with different GOMAXPROCS values | | `-cpuprofile=cpu.prof` | Write CPU profile | | `-memprofile=mem.prof` | Write memory profile | | `-trace=trace.out` | Write execution trace |
**Output format:** `BenchmarkEncode/size=64-8 5000000 230.5 ns/op 128 B/op 2 allocs/op` โ the `-8` suffix is GOMAXPROCS, `ns/op` is time per operat
Read more
name: golang-benchmark
description: "Golang benchmarking, profiling, and performance measurement. Use when writing, running, or comparing Go benchmarks, profiling hot paths with pprof, interpreting CPU/memory/trace profiles, analyzing results with benchstat, setting up CI benchmark regression detection, or investigating production performance with Prometheus runtime metrics. Also use when the developer needs deep analysis on a specific performance indicator - this skill provides the measurement methodology, while `samber/cc-skills-golang@golang-performance` provides the optimization patterns."
user-invocable: true
license: MIT
compatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.
metadata:
author: samber
version: "1.2.7"
openclaw:
emoji: "๐"
homepage: https://github.com/samber/cc-skills-golang
requires:
bins:
- go
- benchstat
install:
- kind: go
package: golang.org/x/perf/cmd/benchstat@latest
bins: [benchstat]
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch Bash(benchstat:*) Bash(benchdiff:*) Bash(cob:*) Bash(gobenchdata:*) Bash(curl:*) mcp__context7__resolve-library-id mcp__context7__query-docs WebSearch AskUserQuestion EnterWorktree ExitWorktree**Persona:** You are a Go performance measurement engineer. You never draw conclusions from a single benchmark run โ statistical rigor and controlled conditions are prerequisites before any optimization decision.
**Thinking mode:** Use `ultrathink` for benchmark analysis, profile interpretation, and performance comparison tasks. Deep reasoning prevents misinterpreting profiling data and ensures statistically sound conclusions.
**Dependencies:**
- benchstat: `go install golang.org/x/perf/cmd/benchstat@latest`
Go Benchmarking & Performance Measurement
Performance improvement does not exist without measures โ if you can measure it, you can improve it.
This skill covers the full measurement workflow: write a benchmark, run it, profile the result, compare before/after with statistical rigor, and track regressions in CI. For optimization patterns to apply after measurement, โ See `samber/cc-skills-golang@golang-performance` skill. For pprof setup on running services, โ See `samber/cc-skills-golang@golang-troubleshooting` skill.
Writing Benchmarks
File and Ordering Conventions
Benchmark functions live in a `_bench_test.go` file named after the source file under benchmark, not after the individual function โ `parser.go` -> `parser_bench_test.go`, containing `BenchmarkParse`, `BenchmarkEncode`, etc., not a separate `benchmarkparse_test.go` per function. Keeping benchmarks in their own file (instead of mixed into `parser_test.go`) keeps `go test -bench=. ./pkg/parser` output free of unrelated `Test*` noise, and separates fixtures sized for measurement (large inputs, long-lived setup) from those sized for correctness โ the two rarely share the same shape. The file still follows Go's one-test-file-per-source-file convention (โ See `samber/cc-skills-golang@golang-testing` skill), just with the `_bench` suffix marking its narrower purpose.
Order `Benchmark*` functions inside `parser_bench_test.go` to mirror the order of the functions/methods they measure in `parser.go` โ a reader comparing the two files top to bottom should find `BenchmarkParse` at the same relative position as `Parse`.
`b.Loop()` (Go 1.24+) โ preferred
For Go 1.24+, prefer `b.Loop()` for new benchmarks. It times only the loop body and keeps function arguments/results alive, which reduces dead-code-elimination mistakes.
func BenchmarkParse(b *testing.B) {
data := loadFixture("large.json") // setup โ excluded from timing
for b.Loop() {
Parse(data) // compiler cannot eliminate this call
}
}Legacy `b.N` loops still compile and are fine to keep when preserving existing benchmarks or supporting Go <1.24. They are easier to get wrong: setup may need `b.ResetTimer()`, and results may need a sink if the compiler can eliminate the work. Go 1.26 fixed an earlier `b.Loop()` inlining limitation โ benchmarks on 1.24โ1.25 already benefit from `b.Loop()` but may miss inlining optimizations that 1.26 delivers.
Memory tracking
func BenchmarkAlloc(b *testing.B) {
b.ReportAllocs() // or run with -benchmem flag
var sink []byte
for b.Loop() {
sink = make([]byte, 1024)
}
_ = sink
}`b.ReportMetric()` adds custom metrics (e.g., throughput):
b.ReportMetric(float64(totalBytes)/b.Elapsed().Seconds(), "bytes/s") // b.Elapsed() is only valid inside b.Loop()
Sub-benchmarks and table-driven
func BenchmarkEncode(b *testing.B) {
for _, size := range []int{64, 256, 4096} {
b.Run(fmt.Sprintf("size=%d", size), func(b *testing.B) {
data := make([]byte, size)
for b.Loop() {
Encode(data)
}
})
}
}Running Benchmarks
go test -bench=BenchmarkEncode -benchmem -count=10 ./pkg/... | tee bench.txt
| Flag | Purpose | | ---------------------- | ----------------------------------------- | | `-bench=.` | Run all benchmarks (regexp filter) | | `-benchmem` | Report allocations (B/op, allocs/op) | | `-count=10` | Run 10 times for statistical significance | | `-benchtime=3s` | Minimum time per benchmark (default 1s) | | `-cpu=1,2,4` | Run with different GOMAXPROCS values | | `-cpuprofile=cpu.prof` | Write CPU profile | | `-memprofile=mem.prof` | Write memory profile | | `-trace=trace.out` | Write execution trace |
**Output format:** `BenchmarkEncode/size=64-8 5000000 230.5 ns/op 128 B/op 2 allocs/op` โ the `-8` suffix is GOMAXPROCS, `ns/op` is time per operat
AI agent skills are reusable instruction sets that extend your coding assistant with domain-specific expertise, loaded on demand so they don't bloat your context. This repository covers Go-specific skills only (language, testing, security, observability, etc.)
Other skills on cc-skills-golang.
- /golang-cli
Golang CLI application development. Use when building, modifying, or reviewing a Go CLI tool โ especially for command structure, flag handling, configuration layering, version embedding, exit codes, I/O patterns, signal handling, shell completion, argument validation, and CLI
Open skill - /golang-code-style
Golang code style conventions โ line length and breaking, variable declarations, control flow clarity, when comments help vs hurt. Use when writing or reviewing Go code, asking about style or clarity, or establishing project coding standards. Not for naming conventions (โ See
Open skill - /golang-concurrency
Golang concurrency patterns. Use when writing or reviewing concurrent Go code involving goroutines, channels, select, locks, sync primitives, errgroup, singleflight, worker pools, or fan-out/fan-in pipelines. Also triggers when you detect goroutine leaks, race conditions,
Open skill - /golang-context
Idiomatic context.Context usage in Golang โ propagation through API boundaries, cancellation, timeouts and deadlines, request-scoped values, context.WithoutCancel for background work outliving requests. Apply when designing context propagation across layers, debugging leaked or
Open skill - /golang-continuous-integration
CI/CD pipeline configuration using GitHub Actions for Golang projects โ testing, linting, SAST, security scanning, code coverage, Dependabot, Renovate, GoReleaser, code review automation, and release pipelines. Use when setting up or improving Go project CI, configuring GitHub
Open skill - /golang-data-structures
Golang data structures โ slices (internals, capacity growth, preallocation, slices package), maps (internals, hash buckets, maps package), arrays, container/list/heap/ring, strings.Builder vs bytes.Buffer, generic collections, pointers (unsafe.Pointer, weak.Pointer), and copy
Open skill

