Commit c4c1e3bd by luoqi

docs(召回): 记录「子场景并发提速」的否定实测 —— I/O 受限,并行无效

2026-08-29 测试服实测(585K 患者 / 87,661 命中,空闲机):
  串行(默认 1):24.6 / 21.7 / 23.5 分钟(三次)
  并发 3:      24.1 分钟 —— 不但没快,还略慢

采样显示全程 DataFileRead:本阶段是共享磁盘 I/O 受限,不是查询延迟受限,
并行只让几条查询抢同一批 page,总读取量不变。要提速得减少读取量(索引/收窄扫描),
不是提高并行度。把这个负结果写进注释,免得后来人再拧一次这个旋钮。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
parent 834a0c3e
...@@ -220,6 +220,14 @@ export class TreatmentInitiationRecallScenario implements PlanScenarioPlugin { ...@@ -220,6 +220,14 @@ export class TreatmentInitiationRecallScenario implements PlanScenarioPlugin {
// 10 个子场景查询彼此独立(各自 SQL + union-find 合并 + 打分,无共享状态); // 10 个子场景查询彼此独立(各自 SQL + union-find 合并 + 打分,无共享状态);
// 合并/去重(下游 hitsByPatient Map + max 分 + Set 比对)与顺序无关 → 并行 = 结果逐字节相同。 // 合并/去重(下游 hitsByPatient Map + max 分 + Set 比对)与顺序无关 → 并行 = 结果逐字节相同。
// PAC_RECALL_SUBSCENARIO_CONCURRENCY=N(>1)开并行(分块 Promise.all);默认串行,行为不变。 // PAC_RECALL_SUBSCENARIO_CONCURRENCY=N(>1)开并行(分块 Promise.all);默认串行,行为不变。
//
// ⛔ **别指望靠这个旋钮提速** —— 2026-08-29 测试服实测(585K 患者 / 87,661 命中,空闲机):
// 串行(默认 1): 24.6 / 21.7 / 23.5 分钟(三次)
// 并发 3: 24.1 分钟 ← 不但没快,还略慢
// 原因:本阶段是**共享磁盘 I/O 受限**,不是查询延迟受限。采样显示全程 DataFileRead,
// 并行只是让几条查询抢同一批 page,总读取量一个字节都没少。
// 要提速得**减少读取量**(索引 / 收窄扫描范围),不是提高并行度。
// (单条最慢的子场景查询 6.7 分钟,其余 12~35 秒 —— 并行后墙钟被最慢那条兜住。)
const conc = Math.max(1, Number(process.env.PAC_RECALL_SUBSCENARIO_CONCURRENCY) || 1); const conc = Math.max(1, Number(process.env.PAC_RECALL_SUBSCENARIO_CONCURRENCY) || 1);
// ⚠️ 不能 hits.push(...subHits):spread 把每个元素当实参压栈,V8 实参上限 ~6.5万; // ⚠️ 不能 hits.push(...subHits):spread 把每个元素当实参压栈,V8 实参上限 ~6.5万;
// host 患者到 ~28 万后单子场景命中可超限 → RangeError: Maximum call stack size exceeded // host 患者到 ~28 万后单子场景命中可超限 → RangeError: Maximum call stack size exceeded
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment