Files
deepseek-harness/.agents/notes/implemented/testing/2026-08-03-opt-in-reasoning-chunk-browser-stress.zh.md

4.3 KiB
Raw Blame History

Agent Note: 需显式启用的推理reasoning分片浏览器压力测试车道

Status: implemented

English | 中文

问题

长推理流引发的浏览器卡死,需要贯穿 fixture测试前置数据异步流、客户端会话归并、React 协调过程和实时 Think 行的完整场景才能显现。小型单元测试可以证明事件语义,却无法暴露渲染器饥饿问题;如果把一个包含 100,000 个分片的场景放入必需的 Web 浏览器测试车道,则每个 PRPull Request都会增加一项缓慢且有意保持失败状态的复现场景。如果生产方按 requestAnimationFrame 的节奏发出事件,渲染器还会对生产方施加隐式背压:页面一旦停滞,生产也随之停滞,从而掩盖触发该回归的实际条件,即网络数据仍会持续到达。

决策

pnpm run test:web:stress 是浏览器性能复现场景的显式入口。其专用 vitest.web-stress.config.ts 只纳入 apps/web/stress-tests/**/*.stress.ts;默认单元测试与 Web 测试配置不会收集该后缀。该命令会先执行构建,因为 Chromium 消费编译生成的客户端产物;压力测试文件会启动宿主脚手架,因此由 tsconfig.host.json 纳管。

推理场景选择确定性的 ?fixture 会话,并让一个需显式启用的 fixture 计时钩子精确发出 100,000 个相互独立的 reasoning-delta 事件。生产方设定的外部到达节奏为每 16 毫秒发出 128 个事件,并在主线程停顿后补发停顿期间本应发出的事件。这样便能近似模拟独立于渲染器而持续到达的字节流,同时无需同步预装载一个巨大的 fixture 队列。一枚结尾标记证明这些事件经过会话归并,并抵达实时 Think 行。

浏览器端启动一个间隔 50 毫秒的心跳,并在启动该流之前调度一个 DOM 事件。最终报告包含已发出的分片数、最大心跳延迟、已调度交互的延迟及心跳样本。两项延迟指标的预算均为 250 毫秒。在回归仍然存在期间,此显式启用命令会打印测量值并以非零状态退出;它由此成为渲染器修复的验收检查,同时不会把已知性能故障设为默认 CI 门禁。DSH_WEB_STRESS_HEADFUL=1 pnpm run test:web:stress 会在可见浏览器中展示同一场景。

默认 fixture 单元测试套件使用三个分片和假定时器来演练该计时钩子。这个小型契约固定输入校验、间隔节奏、并发拒绝、精确事件数及结尾标记交付,而不会把包含 100,000 个分片的工作负载带入 pnpm testpnpm run test:guipnpm run test:web

曾考虑的替代方案

必需的 Web 浏览器场景。 不予采纳:该复现场景目前耗时数十秒,且预期无法满足响应性预算;因此,在生产修复交付之前把它设为必需项会阻塞无关工作。

按动画帧控制节奏。 测量后不予采纳:生产节奏一旦与绘制绑定,生产方就会在渲染变慢时同步减速,使观测到的最大延迟保持在预算以内。这测试的是受背压约束的数据源,而不是问题报告中的连续流工作负载。

同步入队 100,000 个事件。 不予采纳:它会让生产方自身阻塞页面,并让 FxInbox 装入一个通过 shift() 排空的巨大数组,从而把渲染器成本与 fixture 队列机制混为一谈。

真实模型或录制的 HTTP 字节流。 本复现场景不予采纳:实时数据流不具确定性,而 HTTP 层录制会增加 fixture 成本,却无法改进目标断言。内存 fixture 省略 HTTP/SSEServer-Sent Events字节分帧但保留逐个异步会话事件、生产客户端的会话归并过程以及观察到卡死的 React 渲染路径。

后果

开发者现在拥有一条无密钥且可重复执行的命令,它以精确工作负载复现长推理卡死,并输出机器可读的响应性证据。默认测试套件仍然快速且保持通过,但在诊断期间以及接受渲染器修复之前,都必须显式运行该压力测试车道。其计时阈值是浏览器响应性防线,而非吞吐量目标;硬件差异可能改变总时长,但长达数秒的心跳或交互延迟仍明确表示失败。