GUITaboo Async Throughput Root-Cause Audit

Jev 设备、Native、Gateway 与 Provider 时序

三层并发

  1. 设备层:五个 App 的 Jev Run 可以同时探索;本轮不是“一次只跑一个 App”。
  2. Native 层:每个 Run 自己持续产生同步和异步 retained request;异步提交后 APE 继续选动作。JevSemanticReview 使用同一个 JevTransport,同步/异步共用 queue capacity、Gateway 和 provider lease。
  3. 上游层:最终 Gateway 审计显示 Jev limit_count=4、rate_rpm=14,但实际上游发送峰值只有 1,最短发送间隔 4.303 s。这个峰值 1 是共享 Gateway 的 pacing/服务响应共同造成的实际发送结果,不是整个实验只有一个 Native 请求,也不是设备串行。

Gateway 观察窗口内 Jev:正式矩阵调用 1298,含失败尝试的共享窗口调用 1713;上游峰值 1,queue wait 总计 22984.45 s,p50 3.20 s、p95 89.14 s、最大 119.47 s。StartLux 上游峰值 3,queue p95 0.114 s,不能把 Jev 的队列现象外推给 StartLux。

为什么上游峰值 1 仍严重排队

14 RPM 约束了发送速率,而 Native 多设备仍可持续提交。Jev 每次上游调用约 1 s,多个 Run 的请求在共享队列中累积;只要发送节奏低于到达节奏,Gateway queue wait 就会增长。并发上限 4 只是上限,不会把 14 RPM 变成 4 路有效吞吐。

每个 Native JevTransport 自己只有一个 worker(JevTransport.java:164-167),本地 ArrayBlockingQueue 由 submitRetained() 的 waiting.offer() 填充(179-192);cancel() 会从本地 waiting 删除,若已 active 才把连接放入 disconnect queue(81-85)。不同设备/进程的这些 worker 仍共同进入同一个 Gateway queue。当前同步请求没有独立高优先级队列。已经在 Native 侧因 State/version/history 失效或主动取消的异步请求仍可能在 Gateway queue 中等待;队列 timeout 证据与 Native stale/cancelled 指纹高度重合。

取消与队列证据

最终 Jev 关联 Gateway queue timeout 共 147 条,其中 139 条的 body fingerprint 只匹配 Native stale/主动取消请求,8 条因重复 fingerprint 无法唯一归属。典型时间线:

JevTransport.submitRetained() 的 retained lifetime 是 60000 ms,Native 取消调用会停止本地消费,但当前证据表明至少部分请求已经进入共享 Gateway queue 后才失效。是否已经占用 14 RPM 配额取决于是否到达上游发送:queue timeout 本身没有 sent_at,因此只能确认占用队列时间,不能把全部 139 条都算成已消耗上游 RPM。已发送后才取消的请求则会占用一次上游调用;归档没有为每条取消请求提供独立配额扣减字段。

最小调度建议

优先级从低侵入到高收益:

  1. 在 Native/Gateway 边界传播“尚未发送即失效”的取消,避免 stale retained call 继续占 queue;验收要用 body hash 和 received_at/sent_at 对齐。
  2. 在现有共享 queue 内把同步等待请求排在仍未发送的异步请求前;不改变 Pairwise/PROMOTE。
  3. 先限制 Jev 同时活跃的 App Run 数量做可比负载实验;这会降低队列压力,但不能修复本地过早 stale。
  4. 不建议本轮直接改新调度架构;“单 Jev App”能降低负载,却不能证明异步结果能入 Ledger。