perf(embedding,memory): 批上限 4→8 削掉请求放大,审查预算 20s→90s 覆盖实测链长
实测(2026-10-13,本机空闲,活库 cyrene/user 分区 201 条、均长 34.7 汉字): - 一条入库审查召回链 = 51 个「4 条」请求 = 23.070 / 21.860 s;旧审查预算 20s 比链长还短 ⇒ 每一条候选满额的审查都超时,且超时后 **一行留痕都不写** (7 天里 92.1% 的审查 recall_mode 为空、2274 条超时降级的根因) - 同一条链改成「8 条」= 26 个请求 = 21.435 / 21.597 s:请求数减半,墙钟几乎不变 —— 链路耗时由「条数 × 每条成本」主导,批次只改请求数 - 「16 条」在**真实代码路径**上 3 次里 2 次让单请求越过 5s 单次超时(1.818 / 5.016 超时 / 5.001 超时)⇒ 批上限不越过 8;隔离测量里 12 条 0.996~1.017 s 仍在界内 改动: - embedding: perItemBudget 500ms→300ms(实测摊销 70~107ms/条的约 3 倍) ⇒ DefaultBatchLimit 由 (5s/2−100ms)/300ms = **8**,同一套推演、两维都成立 (条数 100ms+8×300ms=2.5s;字符 100ms+480×5ms=2.5s,均在超时的一半内) - embedding: 新增 maxSafeBatchLimit=12(实测外沿)+ 编译期断言(越界即 uint 溢出、 编译失败),与 tidy_config.go 那条同手法 - memory: defaultReviewTimeout 20s→**90s**(> 实测最坏链:空闲 21.6s⇒4.2 倍余量、 与整理链并发 56.7s + T1 8s ⇒ 1.4 倍;不再大的理由=单 worker 有界队列 256 的 最坏积压 256×90s≈6.4h、服务真挂死时第一片 5s 就降级用不到这条预算) 测试(不留过时断言):budget_test.go 加「钉值 8/480 + 两维不等式 + ≤12 外沿 + 16 条必须仍判越界」四层;api_url_test.go 的 reviewBudgetRef 20s→90s; preinsert_recall_test.go 新增跨包断言「预算 > 实测最坏链 + defaultT1Timeout」。 变异自证:perItemBudget 回 500ms ⇒ 钉值断言红;reviewTimeout 回 20s ⇒ 跨包断言红; perItemBudget 150ms(⇒16)⇒ 编译失败(constant -4 overflows uint)。三者均已逐字还原。 遗留(如实登记,未修):① 整理轮每轮重嵌整个分区(user 一轮仍 250 个请求), 解法方向是复用已入库的 vec_items 或给整理轮一个 embedding 请求预算;② 链路对单点 慢分片没有韧性 —— 一个分片失败即整条 Embed 失败、丢掉其余分片的工作量,且实测 任何批次形状都会偶发 >5s 尖峰(4 条 7.139s / 8 条 9.711s,与批次无关),方向是 重试/分片级容错,调常量解决不了。
This commit is contained in:
1 parent
20051f0168
commit
f3fb097630
8 files changed
+280
-53
No files matched your search
@@ -78,10 +78,18 @@ const (
|
||||
//
|
||||
// 🔴 它**不是**拍出来的数字,而是 internal/runtime/embedding 里**同一条推演**
|
||||
// 的结果(budget.go:一次请求的耗时上界 ≤ 单次超时的一半 ⇒ 批上限 = 超时的一半
|
||||
// ÷ 单条预算上界)。2026-10-13:旧值 64 的实测耗时 7.5~8.5s 已越过客户端 5s
|
||||
// 单次超时 ⇒ 客户端放弃、服务端继续算 ⇒ 本机 embedding 服务被顶住,单条请求
|
||||
// (写向量索引)也跟着超时。把批上限与超时绑到同一条推演上,就不会再出现
|
||||
// 「只调一侧、另一侧静默失效」。
|
||||
// ÷ 单条预算上界)。2026-10-13 的实测沿革:
|
||||
// - 旧值 64:单请求实测 6.872s(对比超时 5s)⇒ 客户端放弃、服务端继续算 ⇒
|
||||
// 本机 embedding 服务被顶住,单条请求(写向量索引)也跟着超时;
|
||||
// - 先收到 4:单请求落回界内,但把**一次调用**放大成 ⌈N/4⌉ 个请求 ——
|
||||
// user 分区一轮(CompareLimit 2000 条)就是 500 个请求、审查链 51 个请求;
|
||||
// - 本次放到 **8**(= embedding.DefaultBatchLimit,`perItemBudget` 500ms→300ms):
|
||||
// 同样的分区 500 → **250** 个请求、审查链 51 → **26** 个请求,而单请求实测最大
|
||||
// 1.782s,仍在 5s 之内(16 条/片已复现出 11.043s 的越界单请求,故不取更大)。
|
||||
//
|
||||
// ⚠️ 但它**不缩短整理轮的墙钟**:链路耗时由「条数 × 每条成本」主导,批次只改请求
|
||||
// 数(实测 201 条在 4 条/片与 8 条/片下都是 ~21s)。「整理轮每轮把整个分区重新
|
||||
// 向量化」这个**放大源仍然存在**(user 分区一轮 250 个请求),本切片不动它。
|
||||
//
|
||||
// 批上限在 embedder 内部**还有一道强制**(Embed 自己切片),因此这里即使被改大
|
||||
// 也不会把服务端顶住;这一行只是让调用方别去构造注定被切开的超大切片。
|
||||
|
||||
Reference in new issue
Block a user