perf(plan): share the planning env map via Arc instead of cloning per command#436
Merged
Conversation
… command The planning context's env map — typically hundreds of entries — was copied at every boundary it crossed: once into PlanContext per plan, once per and-item by PlanContext::duplicate, once more per and-item into ScriptCommand::envs, and once per spawn into all_envs. Only the last copy is real work (the spawn env is filtered in place); the rest were clones of an almost-always-identical map. Wrap the map in Arc with copy-on-write: duplication and hand-off points share the map (O(1)), and the two mutation points pay for a copy only when they actually change something — prepend_path once per task node, add_envs only when a command has prefix envs (guarded so an empty prefix set doesn't break sharing). This also prepares for runner-aware caching, which saves each spawn's full env context into the plan; with Arc sharing that addition costs a pointer instead of yet another full copy per spawn. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Member
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
fengmk2
reviewed
Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Motivation
The planning context's env map — the full session environment, typically hundreds of entries — was copied at every boundary it crossed during planning:
PlanContextper plan (plan_query),&&-item byPlanContext::duplicate(each command gets a scoped context),&&-item intoScriptCommand::envsfor program lookup and plan-request callbacks,all_envs.Of these, only the last one does real work — the spawn env is filtered in place by
EnvFingerprints::resolve. Every other copy duplicates an almost-always-identical map just to hand it to the next stage, and the cost scales with task count × command count, not with actual env changes.The immediate trigger is the upcoming runner-aware caching work (#430/#431): it saves each spawn's full env context into the plan (
SpawnCommand::full_envs) sogetEnv/getEnvsand tracked-env validation resolve against the plan rather than the live process env. Without sharing, that would add yet another full map copy per spawn; with this change it costs a pointer.Approach
Wrap the map in
Arcwith copy-on-write semantics:duplicate,ScriptCommand::envs,PlanContext::new) share the map — O(1).prepend_pathonce per task node (package.binPATH prepend), andadd_envsonly when a command actually has prefix envs — an empty prefix set is guarded so it doesn't break sharing.all_envsclone remains, with a comment marking it as the one place the map's contents are genuinely copied.No behavior change;
Sessionalready held the map in anArc, so its call sites are untouched.