Repository navigation
[P0 Performance] workspace-changes git snapshot blocks the first tool of every turn for 27–29 s in large repositories (tested on all 4 releases, including 0.2.2-alpha.3)
#13245
Unanswered
liguanglab
asked this question in
Q&A
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
When a session's working directory resolves inside a git repository,
@deepseek-ai/dsh-workspace-changestakes a fullworking-tree snapshot at
turn/start(git add --all --ignore-errorsinto a scratch index +git write-tree).On a large repository this takes far longer than the plugin's 30 s
timeoutMs, so the first top-level tool call ofevery turn waits 27–29 s before it is dispatched. Later tools in the same turn are normal (0.0–0.2 s).
Not a network, model, MCP or bridge issue — the stalled time is spent inside
git.exechildren.Environment
timeoutMs = 30_000(default)Measured data
One real production session, 992 turns with tool calls:
Tool kind is irrelevant — it is always "the first tool of the turn":
read(native)pwsh(native)Same numbers on every tested release (three runs each, plus an outside-repository control at 0.0 s):
It is the repository, not the directory
Every row is a fresh blank session, same preset, same tool (a
readof a small file), onlycwdchanged:One empty file inside the repository costs 28 s; 20,000 files or 1 GB outside costs 0 s.
File count, text volume, nesting depth and ACLs were each ruled out as the cause.
Snapshot cost itself
git add -Aexecuted exactly the way the plugin does it (emptyGIT_INDEX_FILE):The default
timeoutMs = 30_000is exactly why the observed stall lands at 27–29 s: the git child is killed at 30 sand the turn proceeds without a snapshot.
Reproduction (~2 minutes)
Requires only a DSH instance and its API (
session/create,sessions.prompt, session log). No bridge, no MCP, no QQ.Independent confirmation: during the stall the DSH server has
git.exechildren runningadd --all --ignore-errors, while the Node process itself shows no CPU and no file I/O.Suggested fixes (by benefit / effort)
A UI summary should not gate
tools/execute.git status --porcelain -uno, or track file count/size) and skip thesnapshot past a configurable budget (e.g. 2,000 files / 50 MB).
maxFilestoday bounds only the summary.re-hashed.
enabled: false, or a per-cwd exemption). Note thatdsh-client-ui-deliverablescurrently requires theworkspaceChangesservice, so it must become tolerant of itsabsence (
ctx.get('workspaceChanges')guard), otherwise disabling the plugin breaks that UI.the session (with one warning), instead of paying the cost every turn.
Notes
.gitignoreandgit rm -r --cachedthem so they leave the index; tracked files 2,537 → 492. After that, the same session's firsttool went from 27–28 s to 0.0 / 0.0 / 0.0 s (three consecutive runs).
--inspectbreakpoint insidesnapshotTreewas not completed, so the exact await site insideTurnRecorder.start()is inferred from the code path rather than directly observed. The blocking relationship itselfis established by construction and by the observed
git.exechildren.中文摘要
会话的工作目录落在一个大型 git 仓库内时,
workspace-changes插件在每轮turn/start用临时索引跑git add --all --ignore-errors做工作树快照。仓库大时这条命令要 36.7 s(热)/ 136.2 s(冷),远超插件默认timeoutMs = 30 s,于是每轮第一个工具调用都被挡 27–29 秒(992 轮里 81.7% 首调超过 20 s,中位 27.3 s)。与工具类型、模型、MCP、桥接无关;卡顿期间 DSH 进程零 CPU、零 IO,工作都在
git.exe子进程里。最小复现:仓库内放一个空文件的新目录 → 28.4 s;仓库外放 20,000 个文件或 1 GB 文本 → 0.0 s。
0.2.1-rc.2 / 0.2.2-rc.1 / 0.2.2-rc.3 / 0.2.2-alpha.3 四个版本全部复现,对照均为 0.0 s。
我们愿意配合官方进一步定位此问题,并可提供大体积仓库的极端测试环境。如有测试额度或合作意向,欢迎随时联系
(GitHub: @liguanglab)。
All reactions