diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-03 10:10:50 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-03 10:10:50 +0200 |
| commit | 778706798fc66b9aa6be739517bb1486b3653e58 (patch) | |
| tree | d1451bf6f28c58b9e2f3942aa6ea853bdd7cfde0 | |
| parent | ee86322f832ab13bf6aa165a2f6eec8c1ae7772d (diff) | |
Add benchmark profiling mage targets
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Magefile.go | 64 |
2 files changed, 65 insertions, 0 deletions
@@ -15,6 +15,7 @@ perltidy.ERR *.collapsed *.collapsed.zst *.svg +/bench-profiles/ /.cursor/ REVIEW-COMMENTS.md /.serena/ diff --git a/Magefile.go b/Magefile.go index 09b219c..e2f5b69 100644 --- a/Magefile.go +++ b/Magefile.go @@ -40,6 +40,7 @@ const ( typesGoPath = "internal/types/generated_types.go" typesHeaderPath = "internal/c/types.h" VMLINUXPath = "internal/c/vmlinux.h" + benchProfilesDir = "bench-profiles" integrationParallel = "INTEGRATION_PARALLEL" integrationParallelE = "IOR_INTEGRATION_PARALLEL" ) @@ -126,6 +127,58 @@ func Bench() error { return sh.RunWithV(goEnv(), "go", "test", "./...", "-v", "-bench=.", "-run", "xxx") } +// BenchProf runs pipeline benchmarks and writes timestamped pprof artifacts. +func BenchProf() error { + if err := ensureBenchProfilesDir(); err != nil { + return err + } + + timestamp := benchTimestamp() + cpuProfile := filepath.Join(benchProfilesDir, fmt.Sprintf("pipeline-%s-cpu.prof", timestamp)) + memProfile := filepath.Join(benchProfilesDir, fmt.Sprintf("pipeline-%s-mem.prof", timestamp)) + blockProfile := filepath.Join(benchProfilesDir, fmt.Sprintf("pipeline-%s-block.prof", timestamp)) + + if err := sh.RunWithV(goEnv(), "go", "test", "./internal", + "-run", "^$", + "-bench", "^BenchmarkPipeline", + "-benchmem", + "-count=1", + "-cpuprofile", cpuProfile, + "-memprofile", memProfile, + "-blockprofile", blockProfile, + ); err != nil { + return err + } + + fmt.Println("Profiles written:") + fmt.Println(" ", cpuProfile) + fmt.Println(" ", memProfile) + fmt.Println(" ", blockProfile) + fmt.Println("Analyze with:") + fmt.Printf(" go tool pprof -http=:8080 %s\n", cpuProfile) + fmt.Printf(" go tool pprof -http=:8080 %s\n", memProfile) + fmt.Printf(" go tool pprof -http=:8080 %s\n", blockProfile) + return nil +} + +// BenchCompare runs all benchmarks repeatedly and stores output for benchstat. +func BenchCompare() error { + if err := ensureBenchProfilesDir(); err != nil { + return err + } + + outputFile := filepath.Join(benchProfilesDir, fmt.Sprintf("bench-%s.txt", benchTimestamp())) + cmd := fmt.Sprintf("go test ./... -v -bench=. -run=xxx -benchmem -count=6 | tee %q", outputFile) + if err := sh.RunWithV(goEnv(), "sh", "-c", cmd); err != nil { + return err + } + + fmt.Println("Bench output written to:", outputFile) + fmt.Println("Compare snapshots with:") + fmt.Println(" benchstat bench-profiles/bench-*.txt") + return nil +} + // Generate regenerates all generated files. func Generate() error { fmt.Println("Generating tracepoint and type artifacts...") @@ -377,6 +430,17 @@ func bpfEnv() map[string]string { return map[string]string{"CC": "clang"} } +func ensureBenchProfilesDir() error { + if err := os.MkdirAll(benchProfilesDir, 0o755); err != nil { + return fmt.Errorf("ensure %s: %w", benchProfilesDir, err) + } + return nil +} + +func benchTimestamp() string { + return time.Now().UTC().Format("20060102-150405") +} + func cleanBPFArtifacts() error { for _, pattern := range []string{"internal/c/*.o", VMLINUXPath} { if err := removeFilesByGlob(pattern); err != nil { |
