群内简短结论
1. 复现结果
- 100 并发 session + mock LLM 流式 tool call 大输出,可以稳定复现 BA 卡顿。
- 表现包括:Socket.IO 连接失败、聊天超时、其他接口出现秒级延迟。
2. 版本对比
- v1.0.7 / v1.0.9 相比 v1.0.4 已明显好转。
- session create p50:v1.0.4 约 11.2s,v1.0.9 约 7.2s。
/api/healthp50:v1.0.4 约 6.0s,v1.0.9 约 3.0s。- 但 v1.0.9 仍未完全解决,高并发流式 tool call 下仍会卡。
3. BO / PAT 校验
- 单独压 BO 的 PAT 校验,高并发下确实会排队。
- 但延迟量级小于 BA 端整体卡顿,不太像唯一主因。
4. PyArmor 加密影响
- 本地 release 镜像对比显示,加密版本明显更慢。
- chat 流式处理约慢 1.4x。
- health / models / sessions 等其他接口 p50/p95 大约慢 1.6-1.8x。
5. 初步判断
- 当前瓶颈更像是 BA 运行时在高频流式事件、Socket.IO 连接管理、以及 PyArmor 加密运行时开销上的叠加。
- 建议后续优先看流式事件 fan-out / backpressure / Socket.IO 连接处理,再评估是否调整 PyArmor 加密范围或发布形态。
v1.0.9 vs v1.0.4 session create p50
-36%
11236ms -> 7216ms
v1.0.9 vs v1.0.4 health p50
-51%
6014ms -> 2970ms
PyArmor chat p50 开销
1.41x
85670ms -> 120976ms
PyArmor health p50 开销
1.81x
767ms -> 1384ms
一、镜像版本趋势(box)
这组是同一台测试机器 box,BA 镜像从 1.0.4 切到 1.0.7 和 1.0.9 后复跑。worker 不 OK 主要是 Socket.IO namespace connect 失败或聊天超时;由于 mock LLM 永远只发 tool call,这里 worker OK 不是业务成功率,只表示脚本收到足够多流式 patch 后主动停止。
| 版本 | 总耗时 s | worker 状态 | create p50 ms | create p95 ms | health p50 ms | health p95 ms | models p50 ms | sessions p50 ms | turn patches |
|---|---|---|---|---|---|---|---|---|---|
| BA v1.0.4 镜像(box) | 256.1 | error: 85, timeout: 15 | 11236 | 16246 | 6014 | 7624 | 3084 | 3124 | 2934 |
| BA v1.0.7 镜像(box) | 249.3 | timeout: 21, error: 79 | 7375 | 9803 | 3196 | 3673 | 2767 | 2764 | 5128 |
| BA v1.0.9 镜像(box) | 249.0 | timeout: 24, error: 76 | 7216 | 10069 | 2970 | 4451 | 4382 | 3563 | 5429 |
create p50 趋势
health p50 趋势
二、本地源码与 release 镜像对照
这组用于判断发布形态和 PyArmor 加密的影响。本地 release 镜像都由当前 worktree 构建,未加密和 PyArmor 加密只改 Dockerfile 的 ENCRYPT 参数;两者都连接 box BO 认证,LLM 使用本机 mock。
| 对象 | 总耗时 s | worker 状态 | create p50 | create p95 | chat p50 | health p50 | models p50 | sessions p50 |
|---|---|---|---|---|---|---|---|---|
| 本地源码(无打点) | 105.3 | error: 82, stopped_after_turn_patches: 18 | 5355 | 5754 | 99941 | 484 | 812 | 917 |
| 本地 release 镜像(未加密) | 91.8 | error: 77, stopped_after_turn_patches: 23 | 3471 | 6913 | 85670 | 767 | 1180 | 1062 |
| 本地 release 镜像(PyArmor 加密) | 128.6 | error: 86, stopped_after_turn_patches: 14 | 3951 | 10897 | 120976 | 1384 | 2045 | 1862 |
PyArmor 对比结论
在同一台本机、同一 mock LLM、同一 BO 认证路径下,PyArmor 加密镜像相对未加密镜像:总耗时 1.40x,chat p50 1.41x,health/models/sessions p50 分别为 1.81x、1.73x、1.75x。这说明加密运行时有明显额外开销。
chat p50 对比
三、BO PAT 校验单测
为排除 OAuth/BO 单点问题,额外直接请求 box BO 的 PAT 校验接口。结论是 BO 在高并发下会排队,但延迟量级整体小于 BA 压测中看到的阻塞。
| 测试 | 并发 | 延迟 | 判断 |
|---|---|---|---|
| 单次请求 | 1 | 约 3.7ms | 验证服务本身空载很快 |
| 顺序 100 次 | 1 | p50 4.7ms / p95 5.4ms | 稳定 |
| 1000 次,20 并发 | 20 | p50 23ms / p95 438ms / p99 1.05s | 开始排队,但仍远低于 BA 卡顿量级 |
| 1000 次,100 并发 | 100 | p50 157ms / p95 1.68s / p99 3.07s | 高并发下有排队 |
| 2000 次,200 并发 | 200 | p95 3.11s / p99 5s,22 timeout | BO 有压力,但不足以解释 BA 全部卡顿 |
四、测试说明与限制
- mock LLM 不依赖真实大模型,所有请求都返回一个流式 tool call,内容是写约三万字文件。
- 100 并发压测会同时创建 session、订阅 Socket.IO 并发送 chat 请求,额外探测
/api/health、/api/config/models、/api/sessions?limit=1。 - box 镜像测试和本地源码/镜像测试的绝对值不可直接等同,因为运行机器、容器网络路径和构建形态不同;同组内相对差异更可信。
- 本地镜像连 box BO 时,容器直连 Tailscale 地址会空响应,所以使用宿主机 SSH 转发到 box;认证服务仍是 box BO。
- 本地源码带打点版本用于定位热点;无打点版本更适合和镜像做性能参考。
五、原始报告文件
| 对象 | 路径 | 探针状态 |
|---|---|---|
| BA v1.0.4 镜像(box) | /tmp/ | /api/config/models 200:7/401:35; /api/health 200:41/error:1; /api/sessions?limit=1 200:8/401:34 |
| BA v1.0.7 镜像(box) | /tmp/ | /api/config/models 200:35/401:32; /api/health 200:67; /api/sessions?limit=1 200:35/401:32 |
| BA v1.0.9 镜像(box) | /tmp/ | /api/config/models 200:37/401:21; /api/health 200:58; /api/sessions?limit=1 200:37/401:21 |
| 本地源码(带打点) | /tmp/ | /api/config/models 200:98; /api/health 200:98; /api/sessions?limit=1 200:98 |
| 本地源码(无打点) | /tmp/ | /api/config/models 200:80; /api/health 200:80; /api/sessions?limit=1 200:80 |
| 本地 release 镜像(未加密) | /tmp/ | /api/config/models 200:71; /api/health 200:71; /api/sessions?limit=1 200:71 |
| 本地 release 镜像(PyArmor 加密) | /tmp/ | /api/config/models 200:60; /api/health 200:60; /api/sessions?limit=1 200:60 |