From 3e0245bd3d3a01f32339872d327854f6f12e70eb Mon Sep 17 00:00:00 2001 From: dj-oyu <68707227+dj-oyu@users.noreply.github.com> Date: Tue, 24 Feb 2026 12:47:07 +0900 Subject: [PATCH] perf: replace string concatenation with strings.Builder in hot paths - loop.go: formatCompactEntry/formatLatestEntry (called 4-5x per iteration) - filesystem.go: formatDirEntries loop (per directory entry) - shell.go: executeSync output assembly, fix validatePath to use override-aware cwd instead of original workspace - cron.go: listJobs loop - workspace_ctx.go: cache override sandboxFs in context to reuse across all resolveFS calls within the same tool execution Co-Authored-By: Claude Opus 4.6 --- pkg/agent/loop.go | 23 ++++++++++++++++++++--- pkg/tools/cron.go | 8 +++++--- pkg/tools/filesystem.go | 6 ++++-- pkg/tools/shell.go | 13 ++++++++----- pkg/tools/workspace_ctx.go | 18 ++++++++++++++---- 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index 704f90b37..7ea6247a5 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -1271,11 +1271,23 @@ func formatCompactEntry(entry toolLogEntry) string { args = string(argsRunes[:argsBudget-1]) + "\u2026" } } - return entry.Name + " " + args + " " + result + var sb strings.Builder + sb.Grow(len(entry.Name) + 1 + len(args) + 1 + len(result)) + sb.WriteString(entry.Name) + sb.WriteByte(' ') + sb.WriteString(args) + sb.WriteByte(' ') + sb.WriteString(result) + return sb.String() } // No room for args or args empty - return entry.Name + " " + result + var sb strings.Builder + sb.Grow(len(entry.Name) + 1 + len(result)) + sb.WriteString(entry.Name) + sb.WriteByte(' ') + sb.WriteString(result) + return sb.String() } // formatLatestEntry formats the latest entry command without its result marker. @@ -1294,7 +1306,12 @@ func formatLatestEntry(entry toolLogEntry) string { args = string(argsRunes[:argsBudget-1]) + "\u2026" } } - return entry.Name + " " + args + var sb strings.Builder + sb.Grow(len(entry.Name) + 1 + len(args)) + sb.WriteString(entry.Name) + sb.WriteByte(' ') + sb.WriteString(args) + return sb.String() } return entry.Name } diff --git a/pkg/tools/cron.go b/pkg/tools/cron.go index 562fffc84..2e5bab0e8 100644 --- a/pkg/tools/cron.go +++ b/pkg/tools/cron.go @@ -3,6 +3,7 @@ package tools import ( "context" "fmt" + "strings" "sync" "time" @@ -218,7 +219,8 @@ func (t *CronTool) listJobs() *ToolResult { return SilentResult("No scheduled jobs") } - result := "Scheduled jobs:\n" + var sb strings.Builder + sb.WriteString("Scheduled jobs:\n") for _, j := range jobs { var scheduleInfo string if j.Schedule.Kind == "every" && j.Schedule.EveryMS != nil { @@ -230,10 +232,10 @@ func (t *CronTool) listJobs() *ToolResult { } else { scheduleInfo = "unknown" } - result += fmt.Sprintf("- %s (id: %s, %s)\n", j.Name, j.ID, scheduleInfo) + fmt.Fprintf(&sb, "- %s (id: %s, %s)\n", j.Name, j.ID, scheduleInfo) } - return SilentResult(result) + return SilentResult(sb.String()) } func (t *CronTool) removeJob(args map[string]any) *ToolResult { diff --git a/pkg/tools/filesystem.go b/pkg/tools/filesystem.go index 5ec0ba85c..8130262c1 100644 --- a/pkg/tools/filesystem.go +++ b/pkg/tools/filesystem.go @@ -239,10 +239,12 @@ func formatDirEntries(entries []os.DirEntry) *ToolResult { var result strings.Builder for _, entry := range entries { if entry.IsDir() { - result.WriteString("DIR: " + entry.Name() + "\n") + result.WriteString("DIR: ") } else { - result.WriteString("FILE: " + entry.Name() + "\n") + result.WriteString("FILE: ") } + result.WriteString(entry.Name()) + result.WriteByte('\n') } return NewToolResult(result.String()) } diff --git a/pkg/tools/shell.go b/pkg/tools/shell.go index 3fc90acd7..86246cd98 100644 --- a/pkg/tools/shell.go +++ b/pkg/tools/shell.go @@ -283,8 +283,8 @@ func (t *ExecTool) Execute(ctx context.Context, args map[string]any) *ToolResult cwd = override } if wd, ok := args["working_dir"].(string); ok && wd != "" { - if t.restrictToWorkspace && t.workingDir != "" { - resolvedWD, err := validatePath(wd, t.workingDir, true) + if t.restrictToWorkspace && cwd != "" { + resolvedWD, err := validatePath(wd, cwd, true) if err != nil { return ErrorResult("Command blocked by safety guard (" + err.Error() + ")") } @@ -364,9 +364,11 @@ func (t *ExecTool) executeSync(ctx context.Context, command, cwd string) *ToolRe } } - output := stdout.String() + var ob strings.Builder + ob.WriteString(stdout.String()) if stderr.Len() > 0 { - output += "\nSTDERR:\n" + stderr.String() + ob.WriteString("\nSTDERR:\n") + ob.WriteString(stderr.String()) } if err != nil { @@ -378,8 +380,9 @@ func (t *ExecTool) executeSync(ctx context.Context, command, cwd string) *ToolRe IsError: true, } } - output += fmt.Sprintf("\nExit code: %v", err) + fmt.Fprintf(&ob, "\nExit code: %v", err) } + output := ob.String() if output == "" { output = "(no output)" diff --git a/pkg/tools/workspace_ctx.go b/pkg/tools/workspace_ctx.go index e4adf4aac..7be742ce9 100644 --- a/pkg/tools/workspace_ctx.go +++ b/pkg/tools/workspace_ctx.go @@ -7,11 +7,17 @@ import ( ) type workspaceOverrideKey struct{} +type overrideFsKey struct{} -// WithWorkspaceOverride returns a context carrying a workspace override path. -// Tools will resolve file operations against this path instead of the original workspace. +// WithWorkspaceOverride returns a context carrying a workspace override path +// and a pre-built sandboxFs for that workspace. Tools will resolve file +// operations against this path instead of the original workspace. +// The cached sandboxFs is reused across all resolveFS calls on the same context, +// avoiding per-operation allocation. func WithWorkspaceOverride(ctx context.Context, workspace string) context.Context { - return context.WithValue(ctx, workspaceOverrideKey{}, workspace) + ctx = context.WithValue(ctx, workspaceOverrideKey{}, workspace) + ctx = context.WithValue(ctx, overrideFsKey{}, &sandboxFs{workspace: workspace}) + return ctx } // WorkspaceOverrideFromCtx extracts the workspace override from context, or "". @@ -24,7 +30,7 @@ func WorkspaceOverrideFromCtx(ctx context.Context) string { // resolveFS returns a fileSystem applying workspace override from context. // Paths under "memory/" are excluded (always use original workspace). -// For sandboxFs: creates a temporary instance with the override workspace. +// For sandboxFs: returns the cached override instance from context. // For hostFs (unrestricted): returns as-is. func resolveFS(ctx context.Context, fs fileSystem, path string) fileSystem { override := WorkspaceOverrideFromCtx(ctx) @@ -42,6 +48,10 @@ func resolveFS(ctx context.Context, fs fileSystem, path string) fileSystem { if sfs.workspace == override { return fs } + // Use cached sandboxFs from context + if cached, ok := ctx.Value(overrideFsKey{}).(*sandboxFs); ok { + return cached + } return &sandboxFs{workspace: override} }