Wink Pings

128个会话排队25秒,pi-durable把数据库提交合批后降到0.28秒

每个agent run约12次数据库提交。128个并发会话下,每个run原本要排队约25秒,pi-durable合批后降到0.28秒。性能图很亮眼,评论区的问题更硬:batch失败、ack丢失、工具副作用重放怎么处理。

一个agent run要往数据库写大约12次。128个会话同时跑,每个run排队等约25秒。pi-durable这轮优化后,这个等待变成0.28秒。

Mario Zechner在X上解释了pi-durable的持久化方式:agent每走一步,先保存到数据库,然后才继续。1 save等于1 commit。这样做的目的很直接,跑到一半崩溃,从最近一次commit恢复。约12次commit per run。

pi-durable的提交次数

原来的瓶颈不神秘。session把每个commit单独发到数据库,然后等它返回。一次数据库往返4ms。会话一多,所有commit排在同一条队列里。128个会话时,每个run要等约25秒才轮到自己。

128个会话下的等待时间对比

第二张图的纵轴是log scale。

修复方法:当一个commit正在飞,期间堆起来的commit在下一次数据库调用里一起发。128个会话下,一次db call大约携带33个commit。

合批后一次db call携带的提交数

Mario说这听起来简单,实际棘手。把所有东西简单batch并不能工作,因为单个commit之间可能有读写依赖。这里藏着真正的工作量:合并提交要处理顺序和依赖,不能把一批互相关联的状态硬塞进一个包。

tl;dr也值得看:如果跑一个coordinator,fan out到几十个subagent,后端用postgres或类似数据库,不用再为了吞吐去shard sessions。现在大致只受单CPU饱和限制,因为用的是node。真打到CPU瓶颈,还是得shard。

这轮优化不只对网络数据库有效。本地SQLite快18%到58%,Cloudflare Durable Objects读取的行数少40%,写入的行数少13%,静态内存不变。

不同后端的优化数据

评论区比性能图更像施工图。Maximilian问了一个崩溃场景:数据库提交完一个batch,但调用方还没收到ack,这时杀掉coordinator,再恢复,依赖读和工具调用能不能干净重放。Mario回了yes。Shahid问,如果batch里有一个commit失败,是整批回滚到上次commit重试,还是把坏commit拆出来,让其他32个落地。这个问题没看到回答。Jimmy追问优化到底买的是更少fsync还是写合批。pwguler问瓶颈现在在数据库写速率还是harness。也没看到后续。

还有网友提到,每步先落盘再继续,是过夜agent该有的形状。崩溃后要从上次commit的状态恢复,不是从上次说了什么恢复。12次commit换的是可回放,不是日志好看。这个说法抓住了重点,也留下了更硬的问题:可回放不等于副作用可重放。npm test重跑一次问题不大,工具去发邮件、推代码、扣款,重复执行就很难笑出来。

这轮优化最直接的价值,是把大量并发会话的排队成本摊薄了,让单机CPU成为更清楚的瓶颈。批量提交省掉的是往返和等待,没省掉崩溃恢复、依赖排序、工具副作用去重。性能从25秒到0.28秒很好看,接下来要看的,是batch失败和ack丢失时,系统还能不能把每个会话的状态讲清楚。

来源:Mario Zechner 的 X 帖 https://x.com/badlogicgames/status/2116078693827428383

发布时间: 2026-10-30 19:28