โšก Bolt: [performance improvement] Remove LINQ and iterator allocations in collection mapping

Merged
GO
3mo ago
+146-42

๐Ÿ’ก What: Replaced LINQ chaining (.Select().Where().ToHashSet()) and array instantiations with direct foreach loops and static readonly array references in AgentCliSuggestionProvider.cs, TaskTypePickContext.cs, and WorkspaceSecurityPolicy.cs. For the security policy, nested foreach loops replaced HashSet lookups and LINQ .FirstOrDefault(), preserving the original logic using default(WorkspaceIssueCode?).

๐ŸŽฏ Why: Using LINQ for filtering and mapping over lists generates hidden state machine objects (iterators) that add overhead and cause frequent garbage collection. Creating HashSet and new arrays on each method invocation also compounds memory pressure, especially on frequent operations like UI suggestions and security evaluation loops.

๐Ÿ“Š Impact: Significantly reduces short-lived object allocations and GC pressure, speeding up execution paths that rely on evaluating small sets of strings or object arrays.

๐Ÿ”ฌ Measurement: Review memory profiler or benchmark traces for fewer allocations originating from AgentCliSuggestionProvider.GetSuggestions, TaskTypePickContext.FromCommands, and WorkspaceSecurityPolicy.GetPrimaryIssue.


PR created automatically by Jules for task 1201635121009861489 started by @mta-babel


Summary by cubic

Reduced allocations in command suggestions and workspace security by removing LINQ and iterator allocations on hot paths. Stabilized CI by increasing a test timeout.

  • Refactors
    • Agent CLI suggestions: use shared CreateUsedCommandSet, replace PATH probe with an explicit loop, and extract TryCreateSuggestionPill; keep case-insensitive dedupe without LINQ.
    • TaskTypePickContext and TaskTypeCandidateBuilder: add CreateUsedCommandSet overloads (strings and launches), use them in FromCommands and candidate builder to remove Select/Where.
    • WorkspaceSecurityPolicy: extract AssessAdditionalRisks and ValidateDirectoryTrust; make GetPrimaryIssue allocation-free with static precedence arrays and nested scan, returning null when no precedence match (authorization behavior unchanged).