From e28313faae0a2700e6b5dedb50ad4f2f5ed80df3 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 11 Sep 2026 14:45:49 +0000 Subject: [PATCH] fix(trace): rename TotalCompactions to MaxCompactions ContextState.Compactions is a running counter, so aggregating with max is correct; the old TotalCompactions name was misleading. Rename to MaxCompactions per issue acceptance, document the field, and add tests. Fixes #12 --- internal/classifier/classify.go | 2 +- internal/cli/stats.go | 2 +- internal/trace/metrics.go | 6 +++++- internal/trace/metrics_test.go | 33 +++++++++++++++++++++++++++++++++ internal/trace/types.go | 2 +- 5 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 internal/trace/metrics_test.go diff --git a/internal/classifier/classify.go b/internal/classifier/classify.go index be16cec..b04ee9c 100644 --- a/internal/classifier/classify.go +++ b/internal/classifier/classify.go @@ -75,7 +75,7 @@ func detectBudget(t *trace.Trace) *Classification { func detectContextOverflow(t *trace.Trace) *Classification { maxFill := t.MaxContextFill() - compactions := t.TotalCompactions() + compactions := t.MaxCompactions() if compactions >= 3 && maxFill >= 90 { return &Classification{ diff --git a/internal/cli/stats.go b/internal/cli/stats.go index 3a1ddbb..f590bab 100644 --- a/internal/cli/stats.go +++ b/internal/cli/stats.go @@ -59,7 +59,7 @@ func runStats(cmd *cobra.Command, args []string) error { fmt.Printf("Max context: %.0f%%\n", ctx) } - compactions := t.TotalCompactions() + compactions := t.MaxCompactions() if compactions > 0 { fmt.Printf("Compactions: %d\n", compactions) } diff --git a/internal/trace/metrics.go b/internal/trace/metrics.go index 5564fde..c2cca9e 100644 --- a/internal/trace/metrics.go +++ b/internal/trace/metrics.go @@ -44,7 +44,11 @@ func (t *Trace) MaxContextFill() float64 { return max } -func (t *Trace) TotalCompactions() int { +// MaxCompactions returns the highest ContextState.Compactions value across +// iterations. Compactions is a running counter (compactions so far in the +// loop), so the max is the total observed; the name MaxCompactions matches +// the aggregation (unlike the former TotalCompactions). +func (t *Trace) MaxCompactions() int { var max int for _, it := range t.Iterations { if it.Context.Compactions > max { diff --git a/internal/trace/metrics_test.go b/internal/trace/metrics_test.go new file mode 100644 index 0000000..8094195 --- /dev/null +++ b/internal/trace/metrics_test.go @@ -0,0 +1,33 @@ +package trace + +import "testing" + +func TestMaxCompactions(t *testing.T) { + tr := &Trace{Iterations: []Iteration{ + {Number: 1, Context: ContextState{Compactions: 0}}, + {Number: 2, Context: ContextState{Compactions: 1}}, + {Number: 3, Context: ContextState{Compactions: 4}}, + }} + if got := tr.MaxCompactions(); got != 4 { + t.Errorf("MaxCompactions() = %d, want 4 (max of running counter, not sum 5)", got) + } +} + +func TestMaxCompactionsEmpty(t *testing.T) { + tr := &Trace{} + if got := tr.MaxCompactions(); got != 0 { + t.Errorf("MaxCompactions() = %d, want 0", got) + } +} + +func TestMaxCompactionsOutOfOrder(t *testing.T) { + // Max (not last) so out-of-order iterations still yield the peak counter. + tr := &Trace{Iterations: []Iteration{ + {Number: 3, Context: ContextState{Compactions: 4}}, + {Number: 1, Context: ContextState{Compactions: 0}}, + {Number: 2, Context: ContextState{Compactions: 1}}, + }} + if got := tr.MaxCompactions(); got != 4 { + t.Errorf("MaxCompactions() = %d, want 4", got) + } +} diff --git a/internal/trace/types.go b/internal/trace/types.go index c2aae83..05abdfb 100644 --- a/internal/trace/types.go +++ b/internal/trace/types.go @@ -54,7 +54,7 @@ type ContextState struct { WindowUsed int WindowMax int FillPct float64 - Compactions int + Compactions int // running counter: so far in the loop, not per-iteration CacheHitPct float64 }