diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-05 23:20:32 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-05 23:20:32 +0200 |
| commit | 8311a8726499eef95ebdde86303e766dc3be9179 (patch) | |
| tree | a5efdade9d48d7ec22c566301c19023c55d77314 /Magefile.go | |
| parent | 8db5b64dcfdd9c75e8b9b8dc42f9b263fa00b64b (diff) | |
Add dedicated flamegraph mage benchmark targets
Diffstat (limited to 'Magefile.go')
| -rw-r--r-- | Magefile.go | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/Magefile.go b/Magefile.go index 874cce4..e63a959 100644 --- a/Magefile.go +++ b/Magefile.go @@ -124,7 +124,11 @@ func TestWithName() error { // Bench runs benchmarks. func Bench() error { - return sh.RunWithV(goEnv(), "go", "test", "./...", "-v", "-bench=.", "-run", "xxx") + if err := sh.RunWithV(goEnv(), "go", "test", "./...", "-v", "-bench=.", "-run", "xxx"); err != nil { + return err + } + fmt.Println("Running dedicated flamegraph benchmark suite...") + return BenchFlame() } // PrReview runs a reproducible baseline for Codex-assisted PR reviews. @@ -167,9 +171,69 @@ func BenchProf() error { 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) + fmt.Println("Running flamegraph benchmark profiling...") + return BenchFlameProf() +} + +// BenchFlame runs flamegraph TUI benchmarks with benchmem and repeated samples. +func BenchFlame() error { + return sh.RunWithV(goEnv(), "go", "test", "./internal/tui/flamegraph/", "-run", "^$", "-bench=.", "-benchmem", "-count=5") +} + +// BenchFlameProf runs flamegraph benchmarks and writes CPU/memory profiles. +func BenchFlameProf() error { + if err := sh.RunWithV(goEnv(), "go", "test", "./internal/tui/flamegraph/", + "-run", "^$", + "-bench=.", + "-benchmem", + "-count=1", + "-cpuprofile=flame-cpu.prof", + "-memprofile=flame-mem.prof", + ); err != nil { + return err + } + fmt.Println("Flame profiles written:") + fmt.Println(" flame-cpu.prof") + fmt.Println(" flame-mem.prof") + fmt.Println("Analyze with:") + fmt.Println(" go tool pprof -http=:8080 flame-cpu.prof") + fmt.Println(" go tool pprof -http=:8080 flame-mem.prof") return nil } +// BenchFlameCmp compares flamegraph benchmark runs using benchstat (if installed). +func BenchFlameCmp() error { + if err := ensureBenchProfilesDir(); err != nil { + return err + } + if _, err := exec.LookPath("benchstat"); err != nil { + fmt.Println("benchstat not found in PATH; install with:") + fmt.Println(" go install golang.org/x/perf/cmd/benchstat@latest") + return nil + } + + baseline := filepath.Join(benchProfilesDir, "flame-baseline.txt") + candidate := filepath.Join(benchProfilesDir, fmt.Sprintf("flame-%s.txt", benchTimestamp())) + + if _, err := os.Stat(baseline); errors.Is(err, os.ErrNotExist) { + fmt.Println("No flame baseline found; creating:", baseline) + if err := runFlameBenchToFile(baseline); err != nil { + return err + } + fmt.Println("Baseline created. Re-run mage benchFlameCmp to compare.") + return nil + } else if err != nil { + return err + } + + if err := runFlameBenchToFile(candidate); err != nil { + return err + } + + fmt.Println("Comparing flame benchmark runs:") + return sh.RunWithV(goEnv(), "benchstat", baseline, candidate) +} + // BenchCompare runs all benchmarks repeatedly and stores output for benchstat. func BenchCompare() error { if err := ensureBenchProfilesDir(); err != nil { @@ -450,6 +514,11 @@ func benchTimestamp() string { return time.Now().UTC().Format("20060102-150405") } +func runFlameBenchToFile(outputFile string) error { + cmd := fmt.Sprintf("set -o pipefail; go test ./internal/tui/flamegraph/ -run '^$' -bench=. -benchmem -count=5 | tee %q", outputFile) + return sh.RunWithV(goEnv(), "bash", "-c", cmd) +} + func cleanBPFArtifacts() error { for _, pattern := range []string{"internal/c/*.o", VMLINUXPath} { if err := removeFilesByGlob(pattern); err != nil { |
