From 3f254f23249bcabeec415a4ec90adb9173020e98 Mon Sep 17 00:00:00 2001 From: robertkohahimn Date: Thu, 5 Mar 2026 11:55:33 +0700 Subject: [PATCH] perf(opencode): parallelize git snapshot operations on finish-step Eliminate redundant git add and run write-tree + diff concurrently via Promise.all in new trackAndPatch() method. Fixes #12437 --- packages/opencode/src/session/processor.ts | 26 +++++++------- packages/opencode/src/snapshot/index.ts | 42 +++++++++++++++++++++- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index 67edc0ecfe3..f013128a594 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -250,10 +250,11 @@ export namespace SessionProcessor { input.assistantMessage.finish = value.finishReason input.assistantMessage.cost += usage.cost input.assistantMessage.tokens = usage.tokens + const tracked = await Snapshot.trackAndPatch(snapshot) await Session.updatePart({ id: Identifier.ascending("part"), reason: value.finishReason, - snapshot: await Snapshot.track(), + snapshot: tracked.hash, messageID: input.assistantMessage.id, sessionID: input.assistantMessage.sessionID, type: "step-finish", @@ -261,20 +262,17 @@ export namespace SessionProcessor { cost: usage.cost, }) await Session.updateMessage(input.assistantMessage) - if (snapshot) { - const patch = await Snapshot.patch(snapshot) - if (patch.files.length) { - await Session.updatePart({ - id: Identifier.ascending("part"), - messageID: input.assistantMessage.id, - sessionID: input.sessionID, - type: "patch", - hash: patch.hash, - files: patch.files, - }) - } - snapshot = undefined + if (tracked.patch && tracked.patch.files.length) { + await Session.updatePart({ + id: Identifier.ascending("part"), + messageID: input.assistantMessage.id, + sessionID: input.sessionID, + type: "patch", + hash: tracked.patch.hash, + files: tracked.patch.files, + }) } + snapshot = undefined SessionSummary.summarize({ sessionID: input.sessionID, messageID: input.assistantMessage.parentID, diff --git a/packages/opencode/src/snapshot/index.ts b/packages/opencode/src/snapshot/index.ts index cf254b4cef7..72e2e42231d 100644 --- a/packages/opencode/src/snapshot/index.ts +++ b/packages/opencode/src/snapshot/index.ts @@ -88,13 +88,16 @@ export namespace Snapshot { export async function patch(hash: string): Promise { const git = gitdir() await add(git) + return delta(git, hash) + } + + async function delta(git: string, hash: string): Promise { const result = await $`git -c core.autocrlf=false -c core.longpaths=true -c core.symlinks=true -c core.quotepath=false --git-dir ${git} --work-tree ${Instance.worktree} diff --no-ext-diff --name-only ${hash} -- .` .quiet() .cwd(Instance.directory) .nothrow() - // If git diff fails, return empty patch if (result.exitCode !== 0) { log.warn("failed to get diff", { hash, exitCode: result.exitCode }) return { hash, files: [] } @@ -112,6 +115,43 @@ export namespace Snapshot { } } + // Runs add once, then write-tree and diff concurrently. + export async function trackAndPatch(from?: string): Promise<{ hash?: string; patch?: Patch }> { + if (Instance.project.vcs !== "git" || Flag.OPENCODE_CLIENT === "acp") return {} + const cfg = await Config.get() + if (cfg.snapshot === false) return {} + const git = gitdir() + if (await fs.mkdir(git, { recursive: true })) { + await $`git init` + .env({ + ...process.env, + GIT_DIR: git, + GIT_WORK_TREE: Instance.worktree, + }) + .quiet() + .nothrow() + await $`git --git-dir ${git} config core.autocrlf false`.quiet().nothrow() + await $`git --git-dir ${git} config core.longpaths true`.quiet().nothrow() + await $`git --git-dir ${git} config core.symlinks true`.quiet().nothrow() + await $`git --git-dir ${git} config core.fsmonitor false`.quiet().nothrow() + log.info("initialized") + } + await add(git) + + const [tree, patch] = await Promise.all([ + $`git --git-dir ${git} --work-tree ${Instance.worktree} write-tree` + .quiet() + .cwd(Instance.directory) + .nothrow() + .text(), + from ? delta(git, from) : Promise.resolve(undefined), + ]) + + const hash = tree.trim() || undefined + log.info("tracking", { hash, cwd: Instance.directory, git }) + return { hash, patch } + } + export async function restore(snapshot: string) { log.info("restore", { commit: snapshot }) const git = gitdir()