跳转至

性能回归检查

v2 传输层有一个专门的回归命令:

vp run test:perf:v2-wire

它会运行真实的 v2 投影和客户端 reducer。这一点很重要,因为旧的 built-app 基准测试夹具注入的是 v1 编排事件;在 v2 客户端上运行这些夹具可能会产生令人安心的计时结果,却未覆盖当前活跃的传输路径。

v2 检查固定以下不变式:

  • 冷启动和历史页面在编码行达到约 1 MiB 时停止。包含用户回合的窗口也会在 10 个用户回合(旧页面为 20 个)或 500 行处停止,因此普通回合保持完整。任何其他窗口,包括超过 500 行的单个回合内部,都在 75 行处停止。快照查询在解码载荷之前应用相同的规则。客户端可以选择将大型工作组推迟到展开时再加载。这些组之外的消息和条目继续按正常的历史分页处理。必需的控件记录以及至少一行的规则可能会超出字节目标;该目标并非硬性上限。
  • 有界快照不会保留完整的重复会话消息表。
  • 较早的活动通过有界 HTTP 分页获取,并在不干扰实时滚动窗口的情况下合并。
  • 已确认历史分页的客户端会选用套接字快照回退方案,该方案使用相同的近期历史有界窗口,并携带获取较早历史所需的游标。较旧的客户端和仅 WebSocket 的启动保留兼容的完整快照回退方案。
  • 快照查询按分支祖先限制时间线读取,而不是按总行数:依赖项和控件记录仍伴随窗口。仅凭更小的套接字帧并不能实现整个服务器的内存缩减。
  • 恢复追赶在解码前先检查原始的 1 MiB 持久化载荷预算,然后最多重放 128 个线程事件和 1 MiB 的投影事件 JSON,之后才回退到快照。原始 JSON 字节并非堆内存上限。仅仅因为输出投影较小就提高此预算,可能会在重复的大型工具更新中增加服务器分配。
  • 原始命令输出、动态工具结果主体和内联文件更改主体在传输边界处被省略,包括小输出。显式失败标志和有界结果 ID 保留状态和分组操作计数,而不发送这些主体。推理文本、命令行和搜索结果会随其工作组的加载而发送。子代理提示词和结果以及检查点控件记录仍伴随初始窗口。持久化事件保持完整;现有的 diff 端点在请求时仍提供文件内容。显式的跨环境会话记录导出保留完整的工具主体,以便目标代理能够读取上下文。导出在发送前拒绝超过文件附件限制的时间线 JSON;客户端仍将其附件限制应用于完整文件。
  • 实时命令输出仅通过 orchestration.subscribeCommandOutput 到达客户端,展开的命令行会随自身打开和关闭该订阅。原始输出增量绝不是编排事件:适配器在摄取之前将它们发送到命令输出中心,该中心为每个运行中的命令保留一个有界尾部,并对每个订阅者进行限流。不要通过 turn_item.updated 路由输出增量:繁忙的命令会淹没事件存储,并阻塞所有其他线程的摄取。
  • 初始外壳仅包含活动导航行。已归档的行使用专用的归档查询,会话记录消息主体无论消息大小如何都保留在线程详情中。
  • 外壳恢复发送增量以及紧凑的仓库增强元数据,而不是另一个完整的项目和线程快照。
  • Auto、steer 和 restart 发送在服务器的每线程调度锁内从权威状态解析投递。当服务器声明支持时,模型选择和已识别检查点回滚也会在不先获取完整线程投影的情况下进行调度。较旧的服务器保留基于投影的验证。显式启动发送已经跳过了该读取,因此这种节省并不适用于所有客户端发送路径。

在更改投影模式、分页、外壳同步或线程状态时,请与针对性的包类型检查一起运行此命令,并在每个受影响的界面上进行一次真实客户端测试。传输性能夹具验证契约编码,并对相同合成工作负载的压缩前 RPC JSON 进行比较,同时分别保留历史应用程序对象计数。这些既不是压缩的 WebSocket 捕获,也不是服务器 RSS 的测量,并且命令夹具排除不相关的设置调用和订阅事件。载荷预算应纳入这些测试,以便回归在本地失败。传输预算集成测试(apps/server/integration/transferBudgetV2.integration.test.ts)发送当前客户端发送的选择加入项,并限制以下场景的解码字节和行数:900 行代理回合的有界快照和一个较早页面,以及包含已稳定线程和空闲子代理的侧边栏的冷连接外壳。当客户端获得新的选择加入项时,将其添加到测试的客户端查询中,并为夹具提供该选择加入项所节省的数据。

事件存储与启动

序列游标必须通过索引查找,而不是扫描保留的历史记录。应用程序序列索引包含项目事件和 v2 线程事件;每线程序列索引仅包含 v2 线程事件。仅遗留线程和未知线程必须返回零,且不扫描其他线程。追赶查询保持序列范围以及可选的线程或命令谓词可索引。

启动在读取完整线程投影之前,从当前投影状态中选择恢复候选。候选选择包括排队的运行、待处理的运行时请求、活动提供者会话、后台工作以及未完成的委派投递。在恢复需要的情况下,已归档线程仍会参与。不会仅仅为了确认没有剩余工作而加载已完成的线程历史。

Projection 验证在有界页面中解码规范行(canonical rows),包括共享 provider 记录和 fork 谱系。Rebuild 在其事务内按固定顺序重放事件页面;它必须在投影之前收集整个事件日志。

重点回归覆盖位于 OrchestrationEventStore.sequence.test.ts、ProjectionRecovery.test.ts,以及 apps/server/src 下的 provider 运行时恢复测试中。

背景工作与导航

settlement worker 从 ProjectionStore.getSettlementCandidates 读取活动、未固定(unpinned)且没有显式 settlement 覆盖的线程。它读取最新的 run 和用户消息时间戳,拒绝活动 run 和待处理请求,并使用与 shell 相同的派生逻辑检查后台工作。它不会加载归档历史、fork 谱系、transcript 计数或 provider 会话。orchestrator 在应用 settlement 之前仍会验证当前线程。

已读回执使用 ProjectionStore.getThread 仅加载规范线程元数据。一次访问会使 lastVisitedAt 单调递增,而不会改变 updatedAt 或解码历史。Shell 查询使用覆盖 thread/run 的索引来统计条目数,并使用部分索引来索引非终止(nonterminal)后台条目,包括空闲条目。最新用户消息读取使用按更新时间排序的索引。

命令面板结果会将实时的 VCS 和关联 pull-request 查询租用给可见视口,其中包含一个小的 overscan 区域。当租约释放时,缓存的徽章仍然可用。本地 Git 状态读取会跳过分歧(divergence)计算;需要 ahead/behind 计数的调用方会保留完整的状态路径。缓存的 fetch 失败会共享现有的退避(backoff)策略,并且只记录实际失败的尝试。未变更的桌面环境引导(bootstrap)读取会保留其数组标识,因此轮询不会使订阅者失效。

本地 trace 记录和 provider 事件日志使用异步、串行化的文件写入与轮转。批量同步追加仍会在慢速存储上阻塞服务器事件循环,尤其是在 Windows 上。当一次 trace 写入较慢时,生产者最多保留一个 trace 文件大小的记录,因此用于测量停顿的 spans 能安然度过停顿;只有当磁盘一直卡住时记录才会被丢弃。Provider 日志记录会保留背压(backpressure)机制。关闭时会在关闭其作用域之前排空(drain)已接受的写入。

Relay awareness 会为每个线程排队一个待发布项,并在发送期间线程发生变化时保留一个后续项。Transcript 增量和工具输出不会加入 awareness 工作队列。Run、request 和相关的线程元数据事件则会。配置会在 shell 读取之前被检查,连接变化会使已发布的身份失效,从而让重新链接可以发布未变更的状态。失败的发布会用指数延迟重试最新状态最多五次。新的相关事件会重置预算;成功的发布、禁用或取消链接会取消重试。当预算耗尽后,发布会等待下一个相关事件,而不是在中断期间持续产生流量。

重点覆盖:ProjectionSettlement.test.ts、ThreadSettlementService.test.ts、runtimeLayer.test.ts、AgentAwarenessRelay.test.ts、GitVcsDriverCore.test.ts 和 desktopLocal.test.ts。

移动端循环动画

apps/mobile/package.json 设置 Reanimated 的 DISABLE_COMMIT_PAUSING_MECHANISM,以便键盘避让在 iOS 上可以动画。Reanimated 将该标志文档化为仅与 React Native 的 preventShadowTreeCommitExhaustion 配合使用才是安全的;该选项默认关闭,并且需要从源码构建 React Native,因此我们的构建没有使用它。Reanimated 将每一帧动画提交到 shadow tree;在没有提交暂停机制的情况下,这些提交可能会饿死 React 的提交:JS 线程不断重试其提交,屏幕冻结,返回键无响应。Release 构建会永远重试;dev 构建会以 ShadowTree.cpp: assertion failed (attempts < 1024) 中止。在重内容渲染时仍停留在屏幕上的循环动画应使用 React Native 的 Animated 并设置 useNativeDriver: true,后者无需提交即可更新视图,而不是使用 Reanimated 的 withRepeat。thread-work-log.tsx 中运行中会话的 shimmer 就是一个例子。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 t3/t3code