第13章:从 +3.76% 到 +1.06% —— OwnerMap 广播的工程教训
W7.4-B 独立宇宙挣下的 +3.76% headline 在 W8.7 全局广播开启后掉到 +0.95%,W8.11 批广播只补回 0.11pp。真瓶颈不在 RPC 数量,在 per-Apply 的本地 OwnerMap.Publish 快照重建。本章用完整 ablation 表把这条折损链条讲透,引出『profile 之前不要盲优化』的一条工程铁律
第 11 / 12 章交代了 W14 + W16 + W18 这一整套”跨 CN 一致性”机制的工程实操,也交代了它在 4-CN W=4 ablation 上让吞吐反而比 W7.4-B 独立宇宙差的反直觉结果。本章把 W7.4-B → W8.5 → W8.7 → W8.10 → W8.11 这条广播折损链完整拆开,回答三个问题:W7.4-B 的 +3.76% 是怎么挣出来的?W8.7 全局广播让 delta 掉到 +0.95% 这 1.4pp 折损花在哪?W8.11 批量广播把 RPC 数从 ~3000 砍到 ~90,为什么只补回 0.11pp?最后给出一条可推广的工程教训:真瓶颈不在 RPC 数量、不在网络路径,在 per-Apply 的本地 OwnerMap.Publish 快照重建——这种”瓶颈不在你以为的地方”的情况是性能工程的常态,profile 之前不要盲优化。
📑 目录
- 1. W7.4-B 的 +3.76% headline 是怎么挣出来的
- 2. W8.5 加 hash-det owner —— −1.39pp 的代价在哪
- 3. W8.7 OwnerMap 全局广播 —— 再掉 1.42pp 是为了什么
- 4. W8.10 default-off —— baseline 需要分两条线
- 5. W8.11 批量广播 —— RPC 数砍 33×,吞吐只补 0.11pp
- 6. 真瓶颈不是 RPC,是 per-Apply 本地 OwnerMap.Publish
- 7. 完整 ablation 表与下一个 lever
- 8. 可推广教训 —— “瓶颈不在你以为的地方” 是性能工程的常态
- 自我检验清单
- 参考资料
1. W7.4-B 的 +3.76% headline 是怎么挣出来的
模块十五第 4 章 §8 提到 AURA 的 “fallback to MN atomic CAS” 路径——当 cohort 不是 OWNED 状态,或者 OwnerLockTable 没命中,acquire 会退化成原 CREST 的 MN atomic CAS。这条 fallback 是 AURA 的兜底,但它本身就是 atomic IOPS 物理墙的源头。
W7.4-B 这一步的目标只有一个:让 OWNED 的 acquire 路径完全跳过 MN atomic CAS。
代码层面的关键修复(已在第 11 章 §7 提过,这里展开):
// TxnIO 路径上的 acquire (简化版)
if (kg 在 OwnerLockTable 里 && OWNED@self_cn) {
// W7.4-B: 本地 takeover —— 零填充 lock_buf,跳过 MN CAS
std::memset(lock_buf, 0, sizeof(lock_buf)); // 假装"我成功 CAS 到了"
return Success;
}
// 否则走原 CREST 路径:远端 RDMA CAS
实测路径:在 4-CN W=4 这个工作负载下,每个 CN 在控制环 5ms tick 内能识别 ~250-280 个 hot KG。每个 CN 把自己看到的 hot KG 自己提进 OWNED@self_cn——没有跨 CN 协调,4 个 CN 同时把 KG=37 提成 OWNED@cn0 和 OWNED@cn1 也无所谓。
W7.4-B 4-CN W=4 实测(W8.2 数据):
baseline: 185.02 KOPS
full+takeover: 191.97 KOPS
delta: +6.95 KOPS = +3.76%
细分 metric:
atomic CAS / sec: baseline 1.85M → takeover 1.39M (-25%)
LOCAL acquire hit: ~40%
🍎 直觉解读:4 个 CN 各自把自己看到的 hot KG 提成 “我的本地锁”。任意 CN 跑自己的事务,acquire 落在自己的 OwnerLockTable 上就直接零填充返回,省掉了一次 MN 远端 atomic CAS(CR 的 ~3µs)。每秒省 0.46M CAS × 3µs/CAS ≈ 1.4 秒 CPU 时间 / sec / CN,折成吞吐就是 +3.76%。
⭕ W7.4-B 违反不变式 I1:同一 epoch 下 KG=37 既 OWNED@cn0 又 OWNED@cn1——按 §3.4 不变式 I1 这是非法的。但因为底层 fallback 路径还在(OWNED 的 acquire 失败会自动走 MN CAS,OWNED 的 release 也是如此),不变式被打破不会引起正确性问题——只是失去了”全 CN 对 cohort owner 看法一致”这一个语义保证。
🌟 关键洞察:W7.4-B 是”本地最优解”——它在不引入任何跨 CN 协调的前提下,挣到了 atomic-IOPS 墙的最大可省比例。代价是不变式 I1 被违反,但在 paper §6 figure 5 这个数据点上不用考虑——只看吞吐数字 +3.76% 是漂亮的 headline。
2. W8.5 加 hash-det owner —— −1.39pp 的代价在哪
W7.4-B 之后的下一步是把不变式 I1 重新立起来——也就是说,让单一 KG 在 全 CN 视野下有唯一 owner。W8.5 的方法是 hash-det:
// 决定 KG 的 owner:用 KG ID 取模 num_cns
cn_id_t HashOwnerFor(key_group_id_t kg, std::size_t num_cns) {
return static_cast<cn_id_t>(kg % num_cns);
}
每个 CN 跑控制环时,只有当 HashOwnerFor(kg, 4) == self_cn 才把 KG 提进自己的 OwnerLockTable。
W8.5 4-CN W=4 实测:
baseline: 184.33 KOPS
full+takeover: 188.69 KOPS
delta: +2.37% (vs W8.2 +3.76%,掉了 1.39pp)
为什么掉 1.39pp?
🧠 根因:W7.4-B 下每个 CN 拥有”自己看到的所有 hot KG”——LOCAL hit ~40%。W8.5 下每个 CN 只拥有 1/4 的 KG(按 hash 切分),LOCAL hit 自然降到 ~10%。每秒省 CAS 的次数从 0.46M 降到 ~0.12M,折成吞吐 +2.37% 而不是 +3.76%。
⭐ 这一步的物理代价是”LOCAL hit surface area 缩水”——把 +3.76% 头牌换成 +2.37% 中等收益、换来全 CN 对 owner 看法一致这条不变式。
📑 W8.5 也叫”hash-det singleton” —— 每个 cohort 退化成 1 个 KG,没有真正的 cohort merge;这是 W14 cohort plan 之前的 placeholder。
3. W8.7 OwnerMap 全局广播 —— 再掉 1.42pp 是为了什么
W8.5 让 owner 全 CN 一致,但 OwnerMap 仍然是各 CN 自己维护的本地视图。CN0 把 KG=37 提进 OWNED@cn0,CN1 不知道——CN1 自己的事务走到 KG=37 还是按本地 OwnerMap(认为 KG=37 是 UNKNOWN)走 MN CAS。这是隐式 fallback,但对不变式 I1 是脆弱的——下一次 KG=37 在 CN1 的控制环也命中阈值时,CN1 会再把它提成 OWNED@cn1,hash-det 的”全局一致”语义就被冲掉了。
W8.7 的修复:每次本地 OwnerMap 发生 OWNED 变化时,向所有 peer 广播一个 Handoff RPC:
// TransferController::Apply() 调完本地 PublishMapTransition 之后
if (AuraRuntime::BroadcastEnabled()) {
for (auto peer : known_peers) {
OwnerRpc::Handoff(peer, kg, new_owner_cn); // sync RPC
}
}
每个 peer 收到 Handoff 也把自己的 OwnerMap 同步更新。这样全 CN 视野下 OwnerMap 一致,I1 真正可执行。
实测:
W8.7 4-CN W=4 实测:
baseline: 184.86 KOPS
full+takeover: 186.62 KOPS
delta: +0.95% (vs W8.5 +2.37%,再掉 1.42pp)
下掉 1.42pp 花在哪?
📑 W8.7 的本机开销账:
4-CN W=4 跑 4000 txn 单 rep 约 5s。
control loop 在这 5s 里识别出 ~949 个 promotion。
W8.7 同步路径:每次 promotion 向 3 个 peer 各发一次 Handoff RPC。
Handoff RPC 总数: 949 × 3 = 2847 RPC / CN / rep
RPC 走 loopback TCP,每个 ~5-15µs
总 CPU 时间: 2847 × 10µs ≈ 28ms / CN / rep / 5s = 5.6ms/s
worker thread 抢走 ~5.6ms/s ≈ 0.56% CPU
🤔 0.56% CPU 似乎不至于解释 1.42pp 吞吐下降。还有更隐性的代价:
每个 Handoff 在 peer 端调一次 OwnerLockTable::InstallCohort + Publish。
每次 Publish 触发 OwnerMapSnapshot 重建(见 §6 详解)。
4-CN × 949 promotion × 1 次 peer Publish = ~2847 peer-side Publish。
每次 Publish 是 ~50-100µs 的快照重建。
2847 × 75µs ≈ 213ms / CN / 5s rep = 42.6ms/s ≈ 4.3% CPU
合计 ~5% CPU 占用,对应 ~1.5pp 吞吐降——和实测 1.42pp 匹配。
🌟 结论:W8.7 的代价不只是 RPC 自身的网络开销,更大头是 “peer 端 OwnerMap.Publish” 触发的快照重建。这条线在 W8.11 批量广播下又重演了一次(见 §5)。
4. W8.10 default-off —— baseline 需要分两条线
到 W8.7 这里跑 ablation 矩阵会发现 baseline 数据自相矛盾。
W7.4 时代的 baseline: 185.02 KOPS
W8.7 时代的 baseline: 184.86 KOPS
baseline 都是 CREST 原版(无 AURA),为什么数字不一样?
🧠 根因:CREST 原版的 baseline build 是从 W7.4 commit 拉出来的;W8.7 加了 --aura_broadcast flag 后,flag 的默认值是 true。即便用户跑 baseline 也开了 broadcast——broadcast 路径在 baseline 下虽然不发任何 RPC(没 promotion),但 flag 解析 + AuraRuntime 初始化的额外路径还是花了 microseconds。
W8.10 的修复非常简单:flag default 改成 false,让 baseline 永远走”完全不 touch AURA broadcast 代码”的路径:
// BenchRunner.cc
DEFINE_bool(aura_broadcast, false, // ← W8.10: 默认关
"Enable OwnerMap broadcast to peers via OwnerRpc::Handoff.");
DEFINE_bool(aura_broadcast_batched, false, // ← W8.11: 默认关
"Enable HandoffBatch (W8.11) ...");
实测 baseline 回到了 185.24 KOPS(W7.4 时代水平),ablation 矩阵的对照点重新对齐。
⭕ 可推广的工程教训:任何 ablation flag 的 default 必须是”和 baseline 完全等价”那条路径。default true 的 flag 在 baseline 下不发功能、但代码路径不同——这种”baseline 也被改了”的情况会让 ablation 数据失真,且故障极度隐蔽(错的不是 feature 数据,错的是 baseline 数据)。
🌟 结论一句话:W8.10 不是 feature,是 lab hygiene fix。让对照实验真正”只改一个变量”。
5. W8.11 批量广播 —— RPC 数砍 33×,吞吐只补 0.11pp
W8.7 的 5% CPU 开销分成两块:~0.56% 在 client 侧的 RPC 自身,~4.3% 在 peer 侧的 OwnerMap.Publish。如果不知道这个分账,第一直觉一定是”广播代价大 → 砍 RPC 数量”。这就是 W8.11 的设计动机。
W8.11 引入 HandoffBatch RPC:每个 control loop tick(~30ms)把这个 tick 内的所有 promotion 攒成一条 batch RPC 发给每个 peer:
// TransferController.cc 节选
void BroadcastBatch(const std::vector<Promotion>& promotions) {
for (auto peer : known_peers) {
// 一条 RPC 包含 tick 内所有 promotion
OwnerRpc::HandoffBatch(peer, promotions);
}
}
对端的 server 在处理 HandoffBatch 时,只调一次 OwnerMap.Publish(用 batch 里所有 entries 一起重建一次快照),而不是 N 次:
// OwnerRpcServer.cc::HandleHandoffBatchReq 节选
auto entries = ParseBatch(payload);
for (auto& e : entries) {
lock_table.InstallCohort(e);
}
owner_map.Publish(/*one shot*/); // 整 batch 只 Publish 一次
实测:
W8.11 4-CN W=4:
baseline: 184.64 KOPS
full+takeover: 186.60 KOPS (n=1,CN2 stats-reporter hang)
delta: +1.06% (vs W8.7 +0.95%,恢复 0.11pp)
RPC 数对比:
W8.7 per CN per rep: 949 promotion × 3 peers = 2847 RPC
W8.11 per CN per rep: ~30 ticks × 3 peers = 90 RPC
缩减: 33× 砍掉
🤔 RPC 数砍 33× —— 但吞吐只回补 0.11pp?
📑 分账重新对一下:
| 路径 | W8.7 cost / 5s rep / CN | W8.11 cost / 5s rep / CN | 节省 |
|---|---|---|---|
| client 侧 RPC 自身(TCP 网络) | 2847 × 10µs ≈ 28ms | 90 × 10µs ≈ 0.9ms | −27ms(−0.54%) |
| peer 侧 OwnerMap.Publish | 2847 × 75µs ≈ 213ms | 90 × 75µs ≈ 6.75ms | −206ms(−4.12%) |
| client 侧 per-promotion 本地 Publish | 949 × 75µs ≈ 71ms | 949 × 75µs ≈ 71ms | 0(不动) |
🧠 关键洞察:W8.11 砍掉的是 client RPC + peer Publish,但client 自己的 949 次本地 Publish 一次也没少——每个 promotion 在 TransferController.Apply() 内部还是要 build snapshot + atomic publish 一次。
W8.11 砍掉的总 CPU 是 27 + 206 = 233ms / 5s ≈ 4.66%;client 本地 Publish 占用 71ms / 5s = 1.42%。
🤔 但实测只回补 0.11pp ≈ 0.11% CPU?
⭕ CPU 占用换算到端到端吞吐不是 1:1——线程模型 / contention / coroutine yield 都会吃掉一部分。但 4.66% CPU 节省按经验应该对应 1-2pp 的吞吐回补,实测 0.11pp 显然不正常。
更深层的解释:peer 端的 OwnerMap.Publish 是在 server 网络线程上跑的,它不占 worker thread CPU——所以 worker thread 吞吐基本不受影响。砍掉这 4.12% 节省的是 server 网络线程的负载,而网络线程在 4-CN W=4 这条 workload 下本来就不忙,是 idle 时间被压缩,端到端吞吐看不出变化。
🌟 结论:W8.11 砍 RPC 数其实给的是”controller 整体更省”的隐性收益(监控数据上能看到 server 网络线程 CPU 占用下降),但 worker thread 吞吐没大变——因为 worker 自己的 949 次本地 Publish 一根没省。
6. 真瓶颈不是 RPC,是 per-Apply 本地 OwnerMap.Publish
上一节的分账把真瓶颈指了出来:每次 TransferController.Apply() 内部都调一次 OwnerMap.Publish 重建快照。一个 5s rep 949 次本地 Publish,占 worker thread CPU ~1.4%(71ms / 5s)。
// TransferController::Apply() 简化版(W8.11 时代)
void TransferController::Apply(...) {
// ... freeze / drain / handoff ...
// Phase 4: Publish —— 本地 OwnerMap 快照重建
auto* prev_snapshot = owner_map_->LoadSnapshot();
auto* new_snapshot = OwnerMapSnapshot::CreateFromCopy(prev_snapshot);
new_snapshot->SetCohort(cohort_id, new_owner);
owner_map_->PublishSnapshot(new_snapshot); // ← 75µs / 调用
// Broadcast (W8.7) or BroadcastBatch (W8.11) ...
}
为什么本地 Publish 这么贵?
📑 OwnerMap.Publish 的内部成本:
1. LoadSnapshot():atomic acquire 读当前 snapshot 指针
2. CreateFromCopy():分配新 snapshot + 复制所有 cohort entries
稳态时 cohort 数 ~1000-1200,每个 entry 24 B,复制 ~30KB
3. SetCohort():修改单个 entry
4. PublishSnapshot():CAS 替换 snapshot 指针;旧 snapshot 进 RCU GC 队列
GC 等所有 reader epoch 走完才能 free
🧠 复制 30KB + 一次 atomic publish 单独不慢——但 949 次相加就是 71ms。在控制环 5ms tick 节奏下,平均每 tick 有 ~25 个 promotion,每 tick 累计 25 × 75µs = 1.875ms / 单 CN —— 占 tick wall time 的 37.5%。这就是 control thread 自己跑慢的根因之一。
下一个 lever:把 Publish 折叠到 tick
如果把 Publish 从 per-Apply 改成 per-tick——control thread 每 tick 末尾只调一次 Publish,把 tick 内所有 promotion 一起 commit——就能把 949 次降到 ~30 次(tick 数):
// 未来 W8.12 方向(未实现)
void AuraControlLoop::Tick() {
// ... 跑 PlanCohorts / Apply 决策 ...
std::vector<Promotion> pending;
for (auto& decision : decisions) {
// TransferController.ApplyWithoutPublish() —— 不内部 Publish
tc_->ApplyWithoutPublish(decision);
pending.push_back(decision.promotion);
}
// 单次 Publish
owner_map_->PublishMany(pending);
}
预估收益:~1.4% CPU → ~0.04% CPU,吞吐回补 ~1.2pp。这是从 +1.06% 推回到 ~+2.3% 的下一个 lever。
⭐ 此 lever 没在 paper §6 主线——因为它要拆 TransferController 4 阶段编排的”原子性”。等 paper 投出去再做。
7. 完整 ablation 表与下一个 lever
把 W7.4-B → W8.5 → W8.7 → W8.10 → W8.11 这条折损链做成一张完整 ablation 表:
| Variant | 设计意图 | baseline (KOPS) | takeover (KOPS) | delta | 主要成本来源 |
|---|---|---|---|---|---|
| W7.4-B 原版 | 本地零填充跳 CAS,独立宇宙 | 185.02 | 191.97 | +3.76% | 违反 I1,但代价为 0 |
| W8.5 hash-det only | 全 CN 一致 owner | 184.33 | 188.69 | +2.37% | LOCAL hit 从 40% → 10%(−1.39pp) |
| W8.7 hash-det + broadcast | 全 CN 一致 OwnerMap | 184.86 | 186.62 | +0.95% | RPC 自身 0.56% + peer Publish 4.3%(−1.42pp) |
| W8.10 default-off baseline 修复 | lab hygiene | 185.24 | (同 W8.7) | 同上 | 仅修对照点 |
| W8.11 batched broadcast | 砍 RPC fan-out | 184.64 | 186.60 | +1.06% | client 本地 Publish 不动(仍 1.4% CPU) |
| W8.12 per-tick local Publish(未实现) | 折叠本地 Publish 到 tick | — | ~188 KOPS(预估) | ~+2.3%(预估) | 预期主要剩余可省的本地 Publish |
🌟 核心曲线:+3.76% → +2.37% → +0.95% → +1.06% → +2.3%(预估)。
每一步都是”为了某条不变式 / 一致性 / 工程整洁性付出的代价”——它们都是有意识的决策,不是 bug。但从工程角度,这条折损链有几条可推广的教训:
📑 教训 1:每条”一致性升级”都先在白板上估个 CPU 账
W8.5 是 “1/4 LOCAL hit” → “−1.4pp 吞吐” 的可预测换算;W8.7 是”~2847 sync RPC × 75µs”的可预测换算;W8.11 是”砍 33× RPC + 不动本地 Publish”的可预测换算——这些都可以在写代码之前的 napkin math 阶段估出来。
📑 教训 2:广播代价不只是网络,是触发的所有下游 Publish
W8.7 的下掉 1.42pp 里 4.3% 在 peer Publish,0.56% 在 RPC 网络本身——前者是后者的 8 倍。任何”通知 N 个 peer”的操作,都要先想清楚 peer 端被通知后的反应路径——否则砍网络代价不会真正回血。
📑 教训 3:default-off 是 ablation 的卫生底线
W8.10 这一步看起来微不足道(改 default flag),但没有它,整个 ablation 矩阵都是错的——baseline 数据被污染,所有 delta 都不可信。
8. 可推广教训 —— “瓶颈不在你以为的地方” 是性能工程的常态
把这一章压成一句话:“+3.76% headline → +1.06% reality” 的 2.7pp 折损里,砍 RPC 数那一笔只挣回了 0.11pp。
🧠 为什么 W8.11 之前没有人意识到瓶颈在本地 Publish?
因为”广播代价”这个名字暗示瓶颈在网络。从开发者的视角,看到 “OwnerMap 全局广播 -1.4pp” 第一反应是”批量 RPC 削 fan-out”。这个直觉在 60% 的工程场景下是对的——但这条线偏偏在剩下的 40% 里。
⭕ 如何系统性避免这种偏差:
| 错误习惯 | 正确做法 |
|---|---|
| ”我猜瓶颈在 X → 优化 X" | "X 的开销是什么数量级?整个折损里 X 占多少?” 先 napkin math,再 profile |
| 砍 RPC 数 = 砍代价 | 区分 client RPC 网络代价 vs server 处理代价;后者是前者的 N× 时优化 client 没用 |
| 看到吞吐降,盲优化网络 | flame graph 看 worker thread 占用 → CPU profile worker 路径 → 找到 hot function |
| 改一个 default flag 看不到差 | ablation 默认值必须和 baseline 等价;否则对照实验失效 |
🌟 本章 takeaway 一句话:W8.11 是个完美的反例 —— 我们花了一个完整工程迭代去砍 RPC 数(33× 削减),结果发现这条优化方向解决的是 5% 的问题(client RPC 网络代价),剩下 95% 的瓶颈(本地 Publish)还在原地等下一个 lever。性能工程的核心不是”想到能优化什么”,是”先量出来再说”。
🍎 直觉比喻:性能优化像在森林里追逐脚步声——你听到一个方向有响动就追过去,结果是被风吹的树叶;真正的脚步声在另一个方向、被掩盖在背景噪声里。先静下来听一分钟(profile),再迈步。
⭐ AURA paper §6 的诚实表达:把 +3.76%(W7.4-B headline)作为主线放在 figure 5;把 +1.06%(W8.11 final)作为 ablation table 一行写”with full consistency”;把 +2.3% 的预估 lever(per-tick Publish)放在 §8 future work——不掩盖折损链、不替读者想结论。这是模块十五第 8 章 §4 “negative regimes 诚实展示 trade-off” 的具体执行。
✅ 自我检验清单
- W7.4-B +3.76% 来源:能用”每秒 0.46M 次 atomic CAS × 3µs = 1.4 秒 CPU/sec/CN”算出 +3.76% 的物理含义;能解释为什么”独立宇宙”违反 I1 但不引起正确性问题(fallback 兜底)。
- W8.5 −1.39pp 折损:能解释 LOCAL hit 从 ~40% 缩水到 ~10% 是这一步的代价;能说出”全 CN 一致 owner”换”+1.39pp 吞吐”的物理换算。
- W8.7 −1.42pp 折损分账:知道这 1.42pp 里 ~0.56% 在 RPC 网络本身、~4.3% 在 peer 侧 OwnerMap.Publish 触发的快照重建;能说出”peer 端开销是 client 端 8×”。
- W8.10 lab hygiene:能解释为什么”flag default 必须和 baseline 等价”是 ablation 卫生底线;不修这一条会让所有对照数据失真。
- W8.11 +0.11pp 反直觉:能解释 RPC 数砍 33× 但吞吐只补 0.11pp——根因是被砍掉的 4.3% peer Publish 在 server 网络线程上跑,不占 worker thread;worker 自己的 949 次本地 Publish 一根没省。
- 真瓶颈识别:能徒手说出真瓶颈是
TransferController.Apply()内部的 per-ApplyOwnerMap.Publish快照重建;下一个 lever 是把它折叠到 tick(W8.12 方向)。 - 可推广教训:能说出”广播代价不只是网络、是触发的下游 Publish”、“napkin math 先于 profile 先于优化”、“瓶颈不在你以为的地方是性能工程的常态”这三条结论。
📚 参考资料
概念入门
- “Performance Counter Profiling: Theory and Practice” —— Brendan Gregg, USENIX LISA 2017:性能工程的方法论,“先 profile 再优化” 的经典论述。
- AURA paper §6 (本仓库
paper_lock_ownership_atc_en/sections/6_evaluation.tex):W7.4 → W8.11 完整 ablation 表 + W8.12 future work 段。
关键论文
- “Beyond the Lab: Empirical Studies on Performance Engineering in the Wild” —— Mytkowicz et al., ASPLOS 2009:性能优化中”猜测瓶颈位置”的偏差研究,与本章 §8 教训同源。
- “Tail at Scale” —— Dean & Barroso, CACM 2013:分布式系统下”批量化未必有效”的经典分析;W8.11 砍 RPC fan-out 没补回多少吞吐是这条规律的应用案例。
行业讨论
- “Premature optimization is the root of all evil” —— Knuth, 1974:教科书引用;本章主旨的另一种表达。
- “Why I/O is so slow” —— Bryan Cantrill, Joyent blog 2014:广播代价的实际剖析,与 W8.7 peer Publish 占大头的现象同类。
框架文档
- W8.11 SUMMARY:本仓库
CREST-aura-impl/CREST-Opensource-0007/results/aura_phase4_w811_batched/SUMMARY.md—— 完整的 W8.11 实测数据 + per-CN 折损分析 + 下一个 lever 描述。 - W8.7 SUMMARY:
results/aura_phase4_w87_broadcast/SUMMARY.md—— W7.4 / W8.5 / W8.7 三点对照表 + broadcast 的 future work 选项清单。 - TransferController.cc:
src/transaction/aura/TransferController.cc——Apply()内部 4 阶段编排 + Publish 触发点。 - OwnerMap.cc:
src/transaction/aura/OwnerMap.cc——PublishSnapshot()内部快照重建逻辑(RCU GC + CAS 替换)。