diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..95c39ed --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-05-07 - Avoid Per-Execution Map Allocations +**Learning:** Repeatedly creating map structures (like `colors.ColorMap()`) during per-plugin execution within a parallel loop causes excessive memory allocation and performance overhead. +**Action:** Cache static map data at the instance level (e.g., `StatusLine` struct) during initialization using `sync.Once` to ensure thread-safety, minimize allocations, and maintain backward compatibility. diff --git a/internal/statusline/statusline.go b/internal/statusline/statusline.go index ebbc115..0c6de07 100644 --- a/internal/statusline/statusline.go +++ b/internal/statusline/statusline.go @@ -35,6 +35,8 @@ type StatusLine struct { isIdle bool bashPlugins []plugin.Plugin // Cached discovered bash plugins bashPluginsOnce sync.Once + colorMap map[string]string + colorMapOnce sync.Once } // New creates a new StatusLine renderer @@ -611,6 +613,13 @@ func (sl *StatusLine) getConfigBool(key string, defVal bool) bool { return v } +func (sl *StatusLine) getColorMap() map[string]string { + sl.colorMapOnce.Do(func() { + sl.colorMap = colors.ColorMap() + }) + return sl.colorMap +} + func (sl *StatusLine) runPlugin(name string) string { // Build plugin input input := plugin.Input{ @@ -634,7 +643,7 @@ func (sl *StatusLine) runPlugin(name string) string { ContextWindowSize: sl.input.Context.ContextWindow, }, Config: sl.getPluginConfig(name), - Colors: colors.ColorMap(), + Colors: sl.getColorMap(), } // Try native plugin first (much faster - no subprocess)