Skip to content
预计 1 分钟右侧目录可快速定位

Harness 工作该放 Event Loop、Thread 还是 Process:I/O 与 CPU 并发选择 ​

前置:Harness 共享状态怎么保护:Lock、Coroutine、Thread 与 Process
核心问题:HTTP、阻塞 SDK 和 CPU-heavy 计算分别应该放 Event Loop、Thread 还是 Process,放错位置会怎样拖死 Harness?

async def 不会把 CPU 工作自动变快 ​

Harness 的典型工作可以先分两类:

text
I/O-heavy
- LLM Provider HTTP
- MCP / REST Tool
- DB query
- object storage

CPU-heavy
- 大文本解析/压缩
- 本地 rerank/embedding(取决于实现)
- 图算法
- 图像/音频处理
- 本地模型推理

I/O-heavy 的大量时间是在“等别人”,event loop 可以趁等待去推进其他 Run。CPU-heavy 则一直占执行核,直接放在 event loop 里会让所有 coroutine 的 timer、heartbeat、streaming 都延迟。

一个实用选择表 ​

Workload默认选择原因
async HTTP Model/ToolcoroutineI/O 等待为主
async DB drivercoroutineI/O 等待为主
阻塞式第三方 SDKthread避免卡 event loop
小 JSON/schema validationevent loop 直接做成本很短,切换不划算
数秒纯 Python CPU 计算process / 外部 worker避免 event loop starvation
GPU/本地模型专用执行器/服务有独立资源与并发约束

Thread 的核心价值常常是“把 blocking call 移出 event loop”,而不是保证 CPU-heavy Python 获得多核加速。

Harness 特别怕 Event Loop Starvation ​

如果一次 Context compaction 在 event loop 里连续占 CPU 4 秒,影响的不只是这个 Run:

text
heartbeat 延迟
→ lease 可能误判过期
SSE event 延迟
→ 用户以为卡死
cancellation 延迟
→ Tool 继续消耗资源
timeout callback 延迟
→ deadline 语义失真

因此选择并发模型也是 Runtime correctness 问题,而不只是性能优化。

用 Profiling 决定,不凭函数名 ​

不要看到 embedding() 就默认 CPU-heavy,也不要看到文件 I/O 就默认必须 thread。真正记录:

  • wall-clock time;
  • CPU time;
  • event-loop lag;
  • queue wait;
  • thread/process serialization cost;
  • downstream concurrency limit。

如果工作只有几百微秒,移到 process 的 IPC 成本反而更高。

用 Harness 任务判断并发模型 ​

同一个 Agent Run 里可能同时出现三类工作:

text
等待模型 API / HTTP Tool       → I/O-bound,asyncio 很合适
解析一个中等大小 JSON          → 短 CPU 工作,可直接在 event loop 完成
本地对几十万行代码做重型 AST 分析 → CPU-bound,应考虑 thread/process/offload

危险模式是把“用了 async”误解成“所有函数都不会阻塞”。如果 Tool 在 coroutine 里直接执行一个 3 秒 CPU 密集循环,那么这 3 秒内 event loop 不能及时处理其他 Run 的 heartbeat、cancel 或 stream event。

判断标准不是 API 名字,而是:这段工作的大部分时间是在等待外部 I/O,还是持续占用 CPU;它允许不允许阻塞 event loop;是否需要跨进程隔离。 Runtime 可以把这些特征放进 Tool metadata,由 Executor 选择 async、thread pool、process pool 或独立 worker。

如何验证 ​

制造一个 2 秒纯 Python busy loop,并与 SSE heartbeat、timer 同时运行:

  • 直接放 event loop:应观察到明显 loop lag;
  • 移到 process/合适 executor:heartbeat 与 cancellation latency 应恢复。

自测 ​

  1. HTTP Tool、压缩大文件、CPU 密集解析分别适合 Event Loop、Thread 还是 Process?你的判断依据是什么?
  2. 把 CPU 密集任务直接放进 Event Loop,会怎样反映在其他请求的 latency 上?

Sources ​

AI Engineering · Agent · Harness · Backend Systems