mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2026-08-28 02:34:14 -05:00
fix(terminal): stop parent color stack growing unbounded
ParentColors accumulated every segment ever rendered across the whole process lifetime, never reset - harmless for a one-shot render but quadratic in the pwsh serve daemon, where StreamPrimary keeps calling Primary() in the same long-lived process. Each render's SetParentColors also copied the full history on every call, so cost compounded further. Push onto a real stack instead of prepend-copying, and clear it once per block in String() where the rest of the per-block render state already resets. resolveParentColor's walk order flips to match: nearest ancestor is now the tail, not the head. BenchmarkEnginePrimary at 64000 iterations: 670µs/op -> 16µs/op, flat instead of growing with iteration count; SetParentColors accounted for 99% of all allocated bytes in a mem profile before this change. Entire-Checkpoint: 7b56670e64a2
This commit is contained in:
@@ -26,7 +26,10 @@ func (color Ansi) isKeyword() bool {
|
||||
|
||||
func (color Ansi) Resolve(current *Set, parents []*Set) Ansi {
|
||||
resolveParentColor := func(keyword Ansi) Ansi {
|
||||
for _, parentColor := range parents {
|
||||
// parents is a stack pushed tail-first (see terminal.SetParentColors):
|
||||
// the nearest ancestor is the last element, so walk back-to-front.
|
||||
for i := len(parents) - 1; i >= 0; i-- {
|
||||
parentColor := parents[i]
|
||||
if parentColor == nil {
|
||||
return Transparent
|
||||
}
|
||||
|
||||
+11
-6
@@ -218,15 +218,15 @@ func SetColors(background, foreground color.Ansi) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetParentColors pushes the completed segment's colors onto the parent
|
||||
// stack; the most recent entry (nearest ancestor) sits at the tail. Cleared
|
||||
// per block by String() - see resolveParentColor in color/keywords.go for
|
||||
// the matching tail-to-head walk.
|
||||
func SetParentColors(background, foreground color.Ansi) {
|
||||
if ParentColors == nil {
|
||||
ParentColors = make([]*color.Set, 0)
|
||||
}
|
||||
|
||||
ParentColors = append([]*color.Set{{
|
||||
ParentColors = append(ParentColors, &color.Set{
|
||||
Background: background,
|
||||
Foreground: foreground,
|
||||
}}, ParentColors...)
|
||||
})
|
||||
}
|
||||
|
||||
func ChangeLine(numberOfLines int) string {
|
||||
@@ -602,6 +602,11 @@ func String() (string, int) {
|
||||
|
||||
bgGradientCells, fgGradientCells = nil, nil
|
||||
cellIndex = 0
|
||||
|
||||
// the parent stack is scoped to one block; each new block starts a
|
||||
// fresh ancestor chain. Slicing to zero keeps the backing array so
|
||||
// same-size blocks (the common case) push without reallocating.
|
||||
ParentColors = ParentColors[:0]
|
||||
}()
|
||||
|
||||
return builder.String(), length
|
||||
|
||||
Reference in New Issue
Block a user