跳转至

审查、合入与丢弃要花多少时间?

主要结论

每次新建任务工作区,在 10,000 个文件中修改 20 个、合入 10 个,pVisor stage 的完整机器流程 P50 为 141 ms,Git worktree 为 248 ms,btrfs reflink 副本为 343 ms。stage 适合大工作区的稀疏改动;小工作区 Git 更省时。另一个独立实验中,预备好的 20 文件视图只做审查、合入和丢弃,stage P50 为 27.71 ms,Git 为 4.69 ms。

单独合入已准备好的改动时,10、1,000、10,000 个小文本文件的 pVisor apply P50 分别为 17 ms、0.93 s、14.26 s,均高于 Git patch;100,000 文件出现双峰,两个簇的中位数为 109.73 s 和 196.87 s。完整流程只合入 10 个文件,不能用它的 141 ms 估算全量合入 10,000 个文件的成本。

用户场景 选型含义
大工作区、少量改动、任务工作区用后丢弃 stage 减少创建、扫描和清理整棵工作区的成本
小工作区或已准备并复用的 Git worktree 小工作区及 20 文件预备视图的审查流程 Git 较快;长期复用未测
估算人工监督成本 机器流程不包含人的阅读和判断时间

Motivation

一次 Agent 任务除了执行工具,还需要独立工作区、查看 diff、保留指定改动和清理剩余结果。只比较单项文件操作,会漏掉这些成本。需要频繁创建任务工作区时,应比较完成同样结果的整个流程。

还需分别估算视图已准备好时的审查成本,以及合入文件数增长后的等待和中断恢复成本。三个独立实验分别回答这些问题,不合并样本。

实验设计

完整任务流程:B-WORKFLOW

对照 pVisor rootless stage、Git detached worktree 和 btrfs reflink 副本。输入是预先提交并打包的相同 Git 仓库,分别含 100 或 10,000 个 4 KiB 文件;每次修改 20 个文件,生成全部内容 diff,只合入前 10 个并丢弃其余改动。Git 和 reflink 流程用 git diff 提取选中路径的 patch,先 git apply --check,再合入。

计时涵盖任务视图创建、执行修改、内容审查、选择性合入和清理,按各步骤机器耗时求和。stage 的视图创建包含在 run 中。预先准备输入仓库、为所有对照恢复相同起点,以及测试程序核对结果不计时。已准备并长期复用 worktree 的场景未测。

Linux/x86_64、AMD Ryzen 7 9700X、Fedora 内核 7.2.8-200.fc44.x86_64、btrfs;整个执行树固定到宿主 CPU 0,1。每个后端、规模和合入条件独立采样 30 次、预热 3 次,固定种子随机交替执行,热缓存。Git 自动维护关闭,reflink 强制启用,不能回退成普通复制。冻结制品与源码摘要见下载的来源记录。

普通合入和宿主冲突分别测量。所有样本必须通过完整文件清单和内容校验:执行前后原目录保持原样,普通合入仅改变选中的 10 个文件;冲突条件在合入前修改一个选中宿主文件,要求拒绝整次合入并保留全部宿主内容。stage 还核验 Run Bundle 的暂存和 rootless 隔离证据。失败保留并单列,不作为零耗时;没有按速度剔除样本。两规模 × 两条件 × 三后端共 360 个正式样本,失败 0。

这个固定的文件修改任务不含模型推理、编译或人的阅读时间;Git/reflink 执行是原生进程,不提供相同隔离。冲突测试不覆盖 Git 检查与写入之间的竞态,也不比较崩溃恢复与持久化保证。不能据此给容器、VM 或安全性排名。

预备视图审查:B-SUPERVISION

另一个独立实验只测已准备视图的审查成本:20 个小文本文件已经完成相同修改,查看全部原始/修改内容,合入前 10 个并丢弃其余 10 个。stage 计时包含 status --review --diff、选择性 apply 和 drop;Git 包含完整 diff、选中 patch 提取、git apply --check、apply 和 worktree 移除。工作区创建、任务执行、fixture 和校验均在计时之外。Git 2.55.0 的可执行文件在采样前记录摘要,stage 的冻结制品来源单列;每组 30 次、3 次预热,CPU 0、1,热缓存,无专用宿主内存上限。全部 60 个正式样本通过内容、选择结果和执行边界检查,最终工作区保留供独立审计;没有速度剔除。预备视图单独统计,不计入完整流程表。

合入规模与恢复:B-APPLY

在 AMD Ryzen 7 9700X、Linux 7.2.8-200.fc44 x86_64 上,将被测进程固定到 CPU 0、1;没有另设宿主内存上限。环境采用热缓存,不主动清空页缓存。负载是同一目录中的小文本文件更新,暂存改动和 Git patch 都在计时前生成,工作区准备和计时后的校验另计。

10、1,000、10,000、100,000 文件各测 pVisor apply、Git apply、原生复制、drop 和合入前冲突拒绝。每格预热 3 次、采样 30 次,共 600 个正式计时样本;每轮以固定种子随机交替执行规模和操作。成功样本必须通过完整目标内容和适用的合入账本检查;失败保留并单列,所有有效慢样本保留,不按耗时剔除。

独立正确性检查包括:10,000 文件合入的三个持久化阶段,各做 3 次实际命中的 SIGKILL;以及使用同一二进制的 3 次合入中宿主编辑注入。后者在一个文件已更新、待编辑文件仍为原内容时暂停合入,写入并同步外部改动,再恢复进程。这些检查覆盖有限的注入窗口,不证明任意并发时序。

实验数据和分析

完整任务成本

2026-10-06,同机同批;单位 ms,N=30/格。P95 仅为观察参考。各格没有按预定规则检出分离簇。

工作区文件数 pVisor stage P50 / P95 Git worktree P50 / P95 btrfs reflink P50 / P95
100 109.02 / 110.56 22.02 / 23.14 23.66 / 25.28
10,000 140.82 / 144.38 248.10 / 253.89 343.00 / 349.73

10,000 文件条件下,stage 与 Git 的中位数差为 -107.27 ms, 95% CI [-109.02, -105.60];与 reflink 的差为 -202.18 ms, 95% CI [-204.49, -199.81]。区间来自按随机交替采样轮次配对的 5,000 次 bootstrap,支持 stage 在该场景中更快。100 文件时 stage 与 Git 的差为 +86.99 ms, 95% CI [+77.28, +87.57],与 reflink 的差为 +85.36 ms, 95% CI [+75.45, +85.86],支持小工作区原生流程更快。

预备视图的审查成本

2026-10-06 的独立同批对照;20 个小文本文件,合入 10 个、丢弃 10 个,N=30/格,失败 0。单位 ms,P95 仅作观察参考,各格未触发分簇规则。

步骤 pVisor stage P50 / P95 Git worktree P50 / P95
完整内容审查 6.51 / 7.42 1.28 / 1.47
选择、检查并合入 10 个文件 17.42 / 19.25 2.53 / 3.52
丢弃其余结果 3.60 / 3.87 0.86 / 1.07
逐样本流程合计 27.71 / 29.48 4.69 / 5.86

总耗时的 stage-minus-Git 中位数差为 +23.02 ms,95% CI [22.49, 23.49],来自按采样轮次配对的 5,000 次 bootstrap,支持 Git 在该小型预备视图中更快。步骤中位数不能直接相加得到流程中位数;人工阅读时间未测。选择 stage 的理由是执行边界、暂存和审查接口,单独的小改动审查流程没有速度优势。

成本落在哪些步骤

10,000 文件普通合入,单位 P50 ms,N=30/格。各步骤中位数不能直接相加得到完整流程中位数。

步骤 pVisor stage Git worktree btrfs reflink
创建任务视图 包含在 run 中 83.88 106.82
执行 20 次修改 84.19(含视图创建) 13.31 13.43
查看完整内容 diff 6.95 73.45 151.10
选择、检查并合入 10 个文件 46.22 4.14 4.00
丢弃剩余任务视图 3.49 73.31 67.54

stage 的工具执行和合入仍有额外成本,但创建独立视图、按变化集审查和丢弃不需要处理所有 10,000 个文件。Git/reflink 的整树成本在这个稀疏修改流程中超过了 stage 的额外成本。这个结果支持频繁创建大工作区任务的选型,不代表 stage 的单项读写或编译更快。

宿主冲突的处理成本

合入前改动一个选中宿主文件;完整流程包含创建、执行、审查、拒绝合入和清理。单位 P50 ms,N=30/格。

工作区文件数 pVisor stage Git worktree btrfs reflink 拒绝并完整保留宿主内容
100 95.64 21.66 23.37 三个后端各 30/30
10,000 98.37 248.00 342.22 三个后端各 30/30

没有参与者实验,不能将批量审查或机器耗时换算为人工时间节省。

合入与丢弃的规模成本

2026-10-06 测量。单位:ms;每格为 P50 / 参考 P95,N=30,失败均为 0。30 个样本的 P95 仅描述观察结果,不作为稳定尾延迟承诺。

文件数 pVisor apply Git apply 原生复制 drop 合入前冲突拒绝
10 17.21 / 42.47 1.08 / 1.57 2.56 / 3.07 4.25 / 5.60 2.24 / 2.88
1,000 925.96 / 1,788.33 14.56 / 18.26 16.84 / 19.79 26.99 / 40.03 21.44 / 23.33
10,000 14,259.71 / 21,914.94 155.31 / 173.19 114.55 / 122.87 204.20 / 298.34 183.90 / 200.78
100,000 双峰,见下表 1,639.51 / 1,861.16 1,109.58 / 1,253.46 858.57 / 929.70 1,290.37 / 1,354.08

100,000 文件的 apply 按两簇报告,单位:s。

耗时簇 样本数 比例 簇内中位数
较低耗时 12 40% 109.73
较高耗时 18 60% 196.87

全部 30 个样本的观察范围为 107.42–205.33 s,参考 P95 为 203.99 s。计划大批量合入时应考虑两簇,不能只采用较快一簇作为预算;计时数据本身尚不能确定双峰原因。

和 Git patch 相比,这个成本意味着什么

同轮配对的中位数差异采用 5,000 次 bootstrap,固定种子;单位:ms,每行 30 对样本。

文件数 pVisor apply − Git apply 差异的 95% 置信区间
10 +16.13 +15.79 到 +18.63
1,000 +911.41 +895.05 到 +1,017.69
10,000 +14,104.40 +11,179.77 到 +19,418.50

三个规模均检出 pVisor 更高的耗时;100,000 文件因分布双峰,不给出单一中位数差异。Git patch 也会检查补丁上下文,但它没有提供同一套 preimage 检查、持久化合入账本和中断后的恢复流程。这个对照用于判断同一文本更新的等待成本,不代表两者具有相同事务语义。

合入途中的宿主编辑

独立注入检查使用 10,000 文件,N=3,不与上面的计时样本合并。

有效注入 检出冲突 宿主编辑保留 静默覆盖 状态未知
3 3 3 0 0

三个窗口均明确拒绝冲突并保留宿主编辑、Prepared 账本和完整 upper。冲突发生前已有文件被合入,因此这不意味着整批回滚,也不覆盖最终检查到 rename 之间的所有竞争时序。

SIGKILL 恢复

10,000 文件,每个请求阶段 N=3;9 次都实际命中请求的持久化状态,重新执行后目标和 Committed 账本检查均通过,没有漏失注入窗口。单位:ms,仅报告中位数和观察范围。

中断阶段 恢复中位数 最小值–最大值
prepared 20,790.33 19,599.02–21,358.11
target_applied 386.91 350.96–475.45
committed 428.82 374.26–443.29

恢复等待取决于中断前已经完成的工作。这是进程 SIGKILL 检查,不是断电或存储损坏测试;3 次观察不建立尾延迟或可靠性保证。

适用边界

数据覆盖热缓存、单目录、小文本文件,不涵盖大型二进制、所有文件类型、符号链接和元数据组合,也不涵盖 macOS。完整内容校验在测量时执行;保留的命令和账本已独立核对,清理后的目标目录无法再次逐字节读取。有限的冲突注入不证明任意并发修改都会被检测。

合入规模与恢复的数据

规模耗时 CSV · Git 配对对照 CSV · 恢复检查 CSV · 并发冲突 CSV · 来源摘要 CSV

来源摘要记录二进制、源码、harness 和原始报告的摘要。性能与并发检查使用同一二进制、分别采样;原始命令、报告和审计记录保存在本地 .data/。

数据下载与复现

整理后的表格 CSV · 各步骤统计 · 差异与置信区间 · 来源与制品 · 预备视图各步骤 · 预备视图配对差异 · 预备视图来源 · 证据来源摘要 · 比较方法 · 复现手册