几天前,我发布了一组关于自己AI财务应用的延迟数据,标题写着"所有查询都在一秒以内"。一位读者追问这个基准到底测了什么,我自己一查,75个数据点里有35个是模拟的,不是端到端实测。我立刻撤回了那组数字。
![]()
这是替换版本:全部通过真实上线的生产应用测量,横跨连续三天、六个基准会话,零模拟数据。
先说结论
典型情况:通过已部署应用测得的首字时间(TTFT)平均在2.3到3.6秒之间(每个会话的中位数)。同一个模型调用直接打给推理服务商,只要0.6到1.8秒。
意外的是:几个人同时用这个应用,它就慢得离谱。5个并发用户时,首字时间中位数跳到9到22秒。
还有我暂时解释不了的:大约1.9秒的开销落在模型推理窗口之外,而且"快速"聊天路径的平均表现反而比文档检索(RAG)路径更慢。
更早的时候,我在笔记本上连远程数据库测,首字时间约13秒。去掉四次串行数据库往返、修好缺失的HTTP流式分块头之后,这个初始延迟就消失了。那些旧数字来自本地环境和不同的代码,下面这些才是经过审计、生产验证的测量结果。
怎么测的
目标部署:托管在Render上的线上应用,us-east-2区域的Neon Postgres数据库,通过OpenRouter路由meta-llama/llama-3.1-8b-instruct,使用生产环境的服务商优先级(先Groq,再Novita,最后DeepInfra)。
客户端视角:一台跑在移动蜂窝宽带上的自动化流式客户端,通过公开HTTPS地址连接。
指标定义:首字时间(TTFT)是从客户端发出请求到第一个内容token到达的耗时;完成时间是从请求发出到最后一个token到达、流终止的耗时。
测试协议:三天六个会话(每天两个,10月13到15日),每个会话323次请求,共1938次:
- 120次稳态请求,走热复用的连接
- 40次请求走全新建立的TCP/TLS连接
- 30次直连OpenRouter请求,覆盖三种服务商策略(默认、排除Groq、排除Groq+Novita)
- 60次并发压测请求(c=1、3、5各20次)
- 3次冷启动探测,在服务器空闲间隔之后
- 10次基线网络探测ping
卫生与成本:测试账号用保留的临时域名(@bench.invalid),会话结束时按精确ID从Neon清除(验证残留0行)。1938次请求的OpenRouter推理总成本是0.0108美元。
结果一:应用给原始模型调用加了约1.9秒
注意,这个差值不全是"应用"造成的。一部分来自我笔记本到Render的额外一跳,网络探测(一个轻量端点,所以不是干净的减法)显示这一跳在我的连接上要花几百毫秒甚至更多。这些会话里我没有做服务端追踪,所以不会把剩下的部分归到任何单一原因上。我怀疑的候选是数据库往返、请求中间件和流式开销,但这些都只是猜测。
另外两个我暂时解释不了的现象:
第二天和第三天更慢。第一天的中位数是2.3到2.7秒,第二、三天是3.0到3.6秒。网络探测并没有相应上升。我在查部署的代码或数据在这几天之间是否变了。
"快速"路径反而更慢。快速聊天路径的会话中位数均值约3.4秒,文档(RAG)路径约2.7秒。我本以为会相反——文档检索、向量匹配和重排应该增加延迟,而不是减少。
结果二:新建连接要多花60到714毫秒
在全新连接上,首字到达比复用连接晚60到714毫秒,均值约330毫秒。浏览器会复用连接,所以大多数轮次能跳过这一项,但首次访问的用户要付这笔钱。
结果三:Groq优先的服务商顺序首字快约0.4秒
通过在路由策略里隔离服务商端点,我们测到了上游首字延迟的差异。重要背景:这个测试只评估首字到达。在完整生成基准里,DeepInfra的输出吞吐更低,导致完整响应完成时间明显更长(约10到14秒)。服务商选择是在"瞬间开始流式输出"和"持续输出吞吐"之间做权衡。
结果四:并发瓶颈很快出现
让客户端请求并发穿过已部署应用,暴露出一个事件循环/工作进程的并发墙。3个客户端时,首字中位数比1个客户端慢1.6到3.9倍;5个客户端时慢2.7到4.4倍。这大致相当于服务器基本串行处理请求的表现:k个请求同时到达,中位等待约是单个请求的(k+1)/2倍,3个客户端是2倍,5个是3倍。这跟那个图景一致,但不能证明它。我没有测量是否有东西阻塞了事件循环。第三天在每个层级上都更差,我不知道为什么。
对一个小规模beta来说,单个用户看到约3秒。三个人以上同时聊天就是当前的极限,这是我第一个要修的东西。
结果五:冷启动
空闲期后的第一次请求,六个会话分别是5.4、3.6、3.2、3.8、5.8和6.6秒。这些都是单次运行,所以我报的是范围,不是统计量。第二天第二个会话里,第二和第三次请求也很慢(7.0和6.2秒),我对此没有解释。
汇总百分位(全部720次稳态应用请求)
不只看会话中位数,把相同代码和条件下收集的全部720次稳态请求汇总,得到这样的分布:
- p50(中位数):2842毫秒
- p90:5420毫秒
- p95:7140毫秒
- p99:10680毫秒
我能声称什么、不能声称什么
网络特殊性:所有遥测都来自一个远程蜂窝客户端,通过公开国际路由连到美国东部的服务器部署。用直连光纤或离服务器更近的用户,会经历更低的传输和TLS握手延迟。
服务端拆解:因为基准执行期间服务端追踪是关掉的,应用中间件、模板编译、数据库会话获取和上游代理分发之间的精确毫秒分布仍未验证。
质量与速度:这些基准只隔离响应速度,不对回答的接地性、语义相关性或财务计算准确性做任何评估。
我学到了什么
要测用户路径,不是裸模型。直接模型调用绕过了数据库、会话处理、序列化和网络路由。测裸模型只告诉我OpenRouter有多快,对用户使用应用的体验一无所知。
并发会暴露单用户测试掩盖的东西。2.8秒的单用户响应可用;适度并发下16秒的响应不可接受。并发分析必须从第一天起就是测试的组成部分。
透明建立信任。撤回错误数字很痛苦,但发布经过验证、不加修饰的数据,是唯一重要的标准。
接下来做什么
- 追踪服务端,找出多出来的1.9秒去了哪里,以及为什么快速路径比文档路径慢。
- 修并发行为,然后用同一套测试工具重跑,发布前后对比数字。
- 汇总百分位并附置信区间,按网络和代码版本分组。
- 用足够多的运行次数重做服务商质量对比,看清噪声之外的东西。
- 明天:第二篇文章,讲我质量指标里的一个盲点。有人准确测量了流水线,却仍然漏掉了20个文档问题里有18个从未到达它。
如果你在生产环境的FastAPI/Uvicorn应用里处理过单工作进程的事件循环并发瓶颈,你遇到的主要元凶是什么?
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.