资讯动态

模拟 sleep 不是推理压测:给 llama-server 重建 TTFT 采集

发布时间:2026/10/25 20:58:42 来源:尧图企业网站定制
我想比较两个推理后端第一步却不是让请求并发跑起来而是写清楚“第一”指什么。响应头先到、SSE角色字段先到、第一段非空文本先到是三个不同的时刻。用固定 sleep 替代模型只能测试客户端的等待逻辑。llama.cpp server 文档提供流式接口及服务端计时相关字段。仓库 b11829 标签页面日期为 2026-10-22标记为预发布它不是模型新版本也不能替代本地二进制的提交记录。先固定客户端观察口径这篇把 TTFT 定义为“提交客户端请求”到“读到第一段非空文本”的时间因此包含排队、网络及预填充。另记准入时间可以拆出本地排队。若要研究服务端纯预填充应读取对应版本的服务端日志不能拿这个客户端数值代替。真实实现使用同一进程里的单调时钟。每个请求保存 submit、admit、first_text、done错误与无输出必须单列不能悄悄丢掉再算成功请求平均值。HTTP分块不等于SSE事件一个事件又不必等于一个token解析器要处理跨块、空增量和结束标志。用可检查的事件验证公式下面的整数是人为构造的同一时钟刻度单位任意。程序检查事件顺序并跳过空文本。它没有连接模型也没有采集性能数据。#[derive(Debug, PartialEq)] struct Metrics { queue: u64, ttft: u64, total: u64 } fn metrics(submit: u64, admit: u64, chunks: [(u64, str)], done: u64) - ResultMetrics, static str { if submit admit || admit done { return Err(invalid boundary); } let mut previous admit; let mut first None; for (t, text) in chunks { if t previous || t done { return Err(unordered event); } previous t; if first.is_none() !text.is_empty() { first Some(t); } } let first first.ok_or(no text)?; Ok(Metrics { queue: admit-submit, ttft: first-submit, total: done-submit }) } fn main() { assert_eq!(metrics(10, 20, [(21, ), (35, hi)], 70), Ok(Metrics { queue: 10, ttft: 25, total: 60 })); assert!(metrics(10,20,[(21,)],30).is_err()); assert!(metrics(10,20,[(25,a),(24,b)],30).is_err()); assert!(metrics(20,10,[],30).is_err()); println!(timing boundary checks: 4 passed (synthetic events)); }保存为 main.rs运行rustc --edition2024 main.rs -o demo ./demo。本地 rustc 1.98.0、aarch64 上四项断言通过输出明确标为 synthetic events。这里的25、60只是算术断言不能写成25毫秒TTFT或60毫秒推理。真压测还缺什么下一步接真实服务时我会先固定模型文件哈希、量化类型、上下文长度、server提交、启动参数与提示词集合。客户端日志保存每次请求的状态和原始时间戳预热请求与正式样本分开相同输入长度和输出上限才有比较意义。吞吐量也要分口径服务端报告的生成token数和客户端收集到的字符串长度不是同一单位。统计p50/p95前先说明失败率、样本数、并发以及是否包含排队。跨机器时钟不能直接相减。这轮验证只证明计时归约函数按选定定义工作未完成HTTP解析器、SSE异常恢复或真实模型测量。实际采用的二进制与接口字段应在发布前再查一次。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑