From e029f723cf3b85d63944e193e7ee63fcdbdfff8a Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 02:22:11 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Cache=20color=20map=20to=20?= =?UTF-8?q?reduce=20allocations=20during=20plugin=20execution?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In performance-sensitive areas with parallel execution like `statusline.go`'s `runPlugin`, dynamically calling `colors.ColorMap()` allocates a new, relatively large map for every plugin invocation. Repeatedly allocating maps inside hot loops or goroutines creates unnecessary memory churn and GC pressure. This PR caches the static read-only map at the instance level (using `sync.Once` inside the struct) so it is only allocated once per rendering cycle, rather than re-created inside functions that execute concurrently across multiple routines. Co-authored-by: himattm <6266621+himattm@users.noreply.github.com> --- .jules/bolt.md | 3 +++ internal/statusline/statusline.go | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..0987aa6 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2026-05-02 - Cache Reference Types During Parallel Plugin Execution +**Learning:** In performance-sensitive areas with parallel execution like `statusline.go`'s `runPlugin`, dynamically calling `colors.ColorMap()` allocates a new, relatively large map for every plugin invocation. Repeatedly allocating maps inside hot loops or goroutines creates unnecessary memory churn and GC pressure. +**Action:** Always cache static or read-only maps at the instance level (e.g., using `sync.Once` inside the struct) so they are only allocated once per rendering cycle, rather than re-creating them inside functions that execute concurrently across multiple routines. diff --git a/internal/statusline/statusline.go b/internal/statusline/statusline.go index ebbc115..9be94a3 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 // Cached color map + colorMapOnce sync.Once } // New creates a new StatusLine renderer @@ -634,7 +636,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) @@ -707,3 +709,11 @@ func (sl *StatusLine) getPluginConfig(name string) map[string]any { pluginCfg := sl.config.LoadPluginConfig(name) return map[string]any{name: pluginCfg} } + +// getColorMap returns the color map, creating it once if needed +func (sl *StatusLine) getColorMap() map[string]string { + sl.colorMapOnce.Do(func() { + sl.colorMap = colors.ColorMap() + }) + return sl.colorMap +}