Summary
Optimize GreedyFrequencyStrategy to reduce allocations, bringing it closer to MarginalCostStrategy's efficiency (135 allocs vs 8865 in the large benchmark).
Motivation
Performance analysis from #569 identified several allocation hotspots inherited from the original calculateOptimalWidth(). These were intentionally left unchanged during the strategy extraction to keep the refactoring clean.
Optimization targets
Where iter helps (keep as-is)
splitLines as iter.Seq[string]: avoids []string allocation from strings.Split
maxIndex accepting seq iter.Seq[WidthCount]: lazy hiter.Map avoids []WidthCount materialization
Where iter/lo hurts (fix)
-
transposedRows construction (greedy.go:48-57): hiter.Map + hiter.Concat + hiter.Once + slices.Collect chain causes columns x rows closure calls and slice allocations. lo.Must(lo.Nth(in, columnIdx)) performs O(n) linear scan per cell instead of direct index access.
-
lo.Sum(adjustedWidths) in formatIntermediate: called on every greedy loop iteration. Even when slog.Debug is disabled, the closure arguments are evaluated.
-
adjustToSum (width.go:103-122): loop body creates new slices each iteration via lo.Uniq, slices.SortedFunc, hiter.Nth, slices.Collect(clipToMax(...)), and lo.Sum.
References
Scope
Summary
Optimize
GreedyFrequencyStrategyto reduce allocations, bringing it closer toMarginalCostStrategy's efficiency (135 allocs vs 8865 in the large benchmark).Motivation
Performance analysis from #569 identified several allocation hotspots inherited from the original
calculateOptimalWidth(). These were intentionally left unchanged during the strategy extraction to keep the refactoring clean.Optimization targets
Where
iterhelps (keep as-is)splitLinesasiter.Seq[string]: avoids[]stringallocation fromstrings.SplitmaxIndexacceptingseq iter.Seq[WidthCount]: lazyhiter.Mapavoids[]WidthCountmaterializationWhere
iter/lohurts (fix)transposedRowsconstruction (greedy.go:48-57):hiter.Map+hiter.Concat+hiter.Once+slices.Collectchain causes columns x rows closure calls and slice allocations.lo.Must(lo.Nth(in, columnIdx))performs O(n) linear scan per cell instead of direct index access.lo.Sum(adjustedWidths)informatIntermediate: called on every greedy loop iteration. Even whenslog.Debugis disabled, the closure arguments are evaluated.adjustToSum(width.go:103-122): loop body creates new slices each iteration vialo.Uniq,slices.SortedFunc,hiter.Nth,slices.Collect(clipToMax(...)), andlo.Sum.References
Scope
lo.Nthwith direct index access intransposedRowslo.Sumwithsloglevel check or precomputeadjustToSumloop