Measure performance ¶
Measure a real route or query before changing it. Include authentication, database access and rendering when they are part of the application path.
Ask your agent ¶
Read https://cicadel.fauzaanu.com/en/dev/howto/performance/index.md.
Investigate [slow route or operation] in this application.
Create a representative benchmark, record latency and allocations, and profile it.
Fix the measured bottleneck while preserving behavior and permissions.
Compare repeated runs and report the workload and any remaining uncertainty.Benchmark a handler ¶
Add a benchmark next to the handler you want to measure. This template uses a generated notes app; replace it with the real handler and its dependencies.
package notes
import (
"net/http/httptest"
"testing"
)
func BenchmarkIndex(b *testing.B) {
request := httptest.NewRequest("GET", "/notes/", nil)
b.ReportAllocs()
for b.Loop() {
recorder := httptest.NewRecorder()
Index(recorder, request)
if recorder.Code != 200 {
b.Fatalf("status = %d", recorder.Code)
}
}
}go test ./apps/notes -run '^$' -bench BenchmarkIndex -benchmem -count=5This measures the handler directly. It excludes network, middleware and database costs unless you include them in the setup.
Profile the operation ¶
go test ./apps/notes -run '^$' -bench BenchmarkIndex -benchtime=5s \
-cpuprofile=cpu.out -memprofile=mem.out
go tool pprof -top cpu.out
go tool pprof -top -alloc_space mem.outFor database work, use representative rows in a disposable PostgreSQL database. Check query counts with the application testing helpers and inspect slow SQL with PostgreSQL’s query planner.
Compare a change ¶
Keep the same inputs, dataset and concurrency before and after a change. Record errors as well as latency. Repeat runs; a single short run is not enough to claim a speedup. Do not use a development server’s latency as your production capacity estimate.