[autoresearch] baseline: system prompt quality tests (5/5 passing)

This commit is contained in:
evandrodevbr committed 2026-04-11 05:27:36 -03:00
1 parent 05cc036f6d
commit 60b0101717
142 files changed
+18589 -9947

No files matched your search

@@ -0,0 +1,133 @@
# Go Performance Profiling
## Toolchain
| Tool | Purpose | Command |
|---|---|---|
| `go tool pprof` | CPU / heap / block / mutex profiles | `go tool pprof -text -cum -nodecount=30 profile.pb.gz` |
| `go test -bench` | Micro-benchmarks | `go test -bench=BenchmarkX -benchtime=3s -benchmem -count=3` |
| `go test -cpuprofile` | Capture CPU profile during benchmarks | `go test -bench=BenchmarkX -cpuprofile=cpu.prof` |
| `go test -memprofile` | Capture heap profile during benchmarks | `go test -bench=BenchmarkX -memprofile=mem.prof` |
| `go build -gcflags="-m"` | Escape analysis (what allocates on heap) | `go build -gcflags="-m" ./path/to/pkg 2>&1 \| grep "escapes to heap"` |
| `go test -trace` | Execution trace (goroutine scheduling) | `go test -bench=BenchmarkX -trace=trace.out` |
| `benchstat` | Statistical comparison of benchmarks | `benchstat old.txt new.txt` |
## Data Extraction Script
Use `scripts/go-pprof.sh` to extract profiles into agent-readable markdown.
```bash
# CPU profile from a .prof file
.agents/skills/perf-optimization/scripts/go-pprof.sh cpu path/to/cpu.prof
# Heap profile from a live endpoint
.agents/skills/perf-optimization/scripts/go-pprof.sh heap http://localhost:6060/debug/pprof/heap
# CPU profile from a benchmark (generates and analyzes in one step)
.agents/skills/perf-optimization/scripts/go-pprof.sh bench ./internal/platform/server/... BenchmarkRequireAuth
```
## Go-Specific Optimization Patterns
### Escape Analysis
Before optimizing allocations, run escape analysis to understand WHY values escape to heap:
```bash
go build -gcflags="-m" ./internal/platform/server/ 2>&1 | grep "escapes to heap"
```
Common escape reasons:
- Returning a pointer to a local variable
- Storing a value in an interface (boxing)
- Closure captures
- Slice/map growth beyond initial capacity
### `sync.Pool` for Hot-Path Allocations
**When to use:** The profiler shows a specific type allocated/freed thousands of times per second on the same hot path.
**When NOT to use:** Objects that are long-lived, vary wildly in size, or have cleanup requirements.
```go
var bufPool = sync.Pool{
New: func() interface{} { return new(bytes.Buffer) },
}
func process() {
buf := bufPool.Get().(*bytes.Buffer)
defer func() { buf.Reset(); bufPool.Put(buf) }()
// use buf...
}
```
### Pre-sized Slices and Maps
**Symptom:** `runtime.growslice` or `runtime.mapassign` in the profile — the runtime is repeatedly growing backing arrays.
```go
// ❌ Grows 3 times: cap 0 → 1 → 2 → 4
items := []Item{}
for _, raw := range data { items = append(items, parse(raw)) }
// ✅ One allocation
items := make([]Item, 0, len(data))
for _, raw := range data { items = append(items, parse(raw)) }
```
### `strings.Builder` Over `fmt.Sprintf` in Loops
**Symptom:** `fmt.Sprintf` or `runtime.convTstring` in allocation-heavy loops.
```go
var b strings.Builder
b.Grow(estimatedLen)
for _, part := range parts { b.WriteString(part) }
result := b.String()
```
### Benchmark Best Practices
```go
func BenchmarkX(b *testing.B) {
// Setup OUTSIDE the loop — don't measure init cost
fixture := buildFixture(b)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
result := doWork(fixture)
// Prevent compiler from eliminating the call
_ = result
}
}
```
**Statistical validity:** Always run with `-count=5` minimum and compare with `benchstat`:
```bash
go test -bench=BenchmarkX -benchmem -count=5 > old.txt
# ... make changes ...
go test -bench=BenchmarkX -benchmem -count=5 > new.txt
benchstat old.txt new.txt
```
## Go-Specific Anti-Patterns
1. **Don't use `sync.Pool` for everything.** It's only effective for truly hot paths with uniform objects. Misuse adds complexity without measurable gain.
2. **Don't fight the GC.** Go's GC is tuned for latency. If throughput matters more, tune `GOGC` before rewriting code.
3. **Don't use `unsafe` for performance.** The compiler's escape analysis and inlining are usually sufficient. `unsafe` breaks memory safety guarantees.
4. **Don't ignore `-race` when benchmarking.** Always verify correctness with `-race` before measuring performance without it.
## Irreducible Floors in Go
These are performance costs you cannot eliminate — recognize them and stop:
| Function | What it is | Why it's irreducible |
|---|---|---|
| `p256MulInternal` | P-256 scalar multiplication (ECDSA) | Hardware-optimized assembly |
| `runtime.mallocgc` | Go memory allocator | Symptom, not cause — fix the caller |
| `runtime.gcBgMarkWorker` | GC mark phase | Proportional to allocation rate — fix allocs |
| `runtime.futex` / `runtime.usleep` | OS synchronization | Scheduling overhead |
| `syscall.Syscall` | Kernel calls (I/O) | Irreducible for actual I/O ops |
| `crypto/aes` | AES encryption | Hardware AES-NI, cannot improve |