1. 执行摘要
Linux 内核中渗透着大量决定系统行为的常量——这些"魔数"一旦编译便无法在线修改, 而其最优取值却与硬件代际、负载特征深度耦合。Xkernel 提出 Scoped Indirect Execution (SIE) 机制, 把"指令替换"这一看似不可能的问题转化为"状态更新"问题,从而在已部署的运行内核上对任意 性能关键常量(perf-const)实现毫秒级、安全、可编程的在线调优。
核心贡献
- 原则化的 OS 性能可调性框架——首次在 Linux 上对任何 perf-const 提供 in-situ 调优能力,无需重编译与重启[1]。
- SIE 机制——通过 Critical Span (CS) 与 Safe Span (SS) 的二元作用域设计,把指令替换问题转化为状态更新问题,同时保证版本原子性与副作用安全[1]。
- 基于 eBPF 的可编程策略平面——Xk-tune 让用户以 C-类 DSL 表达调优策略,由 Xk-runtime 转译并注入运行中内核[1]。
- 跨五个子系统的实证收益——块层、中断、内存、NUMA、TCP 拥塞控制均验证显著加速[1]。
- 开源实现——1.7K 行内核 C 代码 + 11K 行 Python 工具链,覆盖完整的离线分析与在线运行时[1]。
2. 背景:被魔数统治的内核
现代 Linux 内核中有数以千计的"性能关键常量"(perf-consts),它们以宏、字面量、静态整数等形式嵌入源码, 控制着阈值、时间间隔、批大小、缩放因子等关键行为参数。
2.1 Perf-Consts 的四大类别
论文将 perf-const 按其对运行时行为的影响分为四类§2.1:
| 类别 | 作用机理 | 论文示例 | 性能敏感性 |
|---|---|---|---|
| 阈值 (Threshold) | 作为限制或边界,触发行为变化 | MAX_SOFTIRQ_RESTART 10 |
CPU 利用率 vs 尾延迟权衡 |
| 间隔 (Interval) | 控制延迟或周期性动作的频率 | IPVS_SYNC_SEND_DELAY (HZ/50) |
同步开销 vs 流量粒度 |
| 批量大小 (Batch Size) | 每次操作合并处理的单位,摊销成本 | BLK_MAX_REQUEST_COUNT 32 |
顺序合并 vs 单请求延迟 |
| 缩放因子 (Scaling Factor) | 调整幅度或强度的乘数 | delta *= 4; |
算法收敛速度与稳定性 |
2.2 魔数从何而来
论文在多处引用了 Linux 内核中真实存在的"开发者自白"§1:
"16 worked well to reduce lock contention … 32 worked in my testing as well." — 块层开发者注释
"[values] are arbitrarily chosen [40]" / "just happen(ed) to work well [38]." — 论文 §1 转述
这些值在诞生当时基于特定硬件与负载,但 Linux 内核一旦合并便几乎不再更新—— 论文统计,145 个 sysctl 性能相关旋钮中有 96 个自 2005 年以来未变§2.2。 随着 NVMe、RDMA、异构内存等新硬件出现,绑定在源码里的魔数迅速成为性能瓶颈。
2.3 现有机制为何不解决问题
sysctl / sysfs
- 非通用机制——需为每个常量手写暴露代码
- 粒度固定为全局,cgroup / 进程级需重新改源码
- 接口被视为内核 ABI,优先稳定性而非灵活性
- 20/145 的转换引入 bug,多为并发问题
- 43 个旋钮存在竞态或不一致状态风险
Kernel Live Patching (KLP)
- 需要重编译 + 二进制差异,分钟级延迟
- 以函数为补丁单位,跨函数(内联)调优脆弱
- 无副作用安全保证,多线程下状态一致性弱
- 不适合快速策略适应与在线调优
Xkernel
- 对任何 perf-const 按需变成可调旋钮
- eBPF 策略,灵活粒度(PID / 设备 / cgroup / 自定义)
- 无需重编译 / 重启,毫秒级生效
- CS + SS 双作用域保证副作用安全
- 开源实现,向用户态泛化
2.4 三大技术挑战
论文 §1 明确提出要让 Xkernel 工作必须解决三件事§1:
- 精确定位消费常量的指令——编译器优化(常量折叠、强度削减、传播)会让源代码中的
#define V 5在二进制中面目全非。 - 为新值生成指令——无法重编译,必须在运行时合成与现有指令正确交互的代码,避免寄存器冲突。
- 处理已产生的副作用——原始值已经传播到运行时状态,"重启"能解决但与"在线调优"的目标冲突。
3. 动机案例:BLK_MAX_REQUEST_COUNT 的两副面孔
块 I/O 层常量 BLK_MAX_REQUEST_COUNT 控制 I/O 请求在下发前的攒批数量——
同一常量在 HDD 与 NVMe 上几乎应取相反值。
3.1 十五年的进化
3.2 量化收益
论文在 7200-RPM SAS HDD 与 NVMe SSD + RocksDB 两种硬件上做了对照实验§2.1。
图 1:同一常量 BLK_MAX_REQUEST_COUNT 在不同硬件与负载下的最佳值差异巨大。
HDD 上 128 比默认值 32 高 7×(读)/ 54×(写),NVMe + RocksDB 上 1 比默认值 32 高 1.2× 吞吐 + 1.37–1.41× 更低延迟。
3.3 这个案例的隐喻
BLK_MAX_REQUEST_COUNT 揭示了一个比"魔数该改"更深的命题:
同一台机器上同时存在 HDD 与 NVMe 时,"最佳参数"这一概念本身就不再是一个标量,而是一个函数—— 取决于具体硬件、具体负载、甚至具体进程/线程的角色。Xkernel 把这个函数从"编译时写死"解放到"运行时表达"。
4. 设计目标与原则
Xkernel 给自己的设计设定了五个硬性目标,任何工程取舍都要回到这些目标上验证§2.3。
- 透明原位调优:不重编译、不重新部署、不重启
- 可编程 + 灵活粒度:用户可表达复杂算法,按需选择作用对象(cgroup、设备、流等)
- 开箱即用:支持内核中任何 perf-const,与标准分发完全兼容
- 毫秒级策略更新:低开销,适合在线反馈循环
- 系统安全性:调优不能产生不一致状态
- 版本原子性 + 副作用安全:比 KLP 更强的并发保证
4.1 五项设计原则
论文 §3.2 总结了 SIE 设计的五条原则§3.2:
- 值更新与调优策略分离——SIE 只做机制(mechanism),策略交给 eBPF。
- 合成状态更新代码而非打补丁——把指令替换问题转化为通用状态更新函数。
- 可复用的离线分析——每个 perf-const 一次性离线成本,结果可跨未来值和策略复用。
- 版本原子性与副作用安全解耦——前者由 CS 保证,后者由 SS 封装。
- 封装内核写、开放自由读——Xk-tune 可读内核任意状态,但写入走 SIE 单通道。
5. SIE:Scoped Indirect Execution
SIE 的核心洞察是:常量虽然被编译器"烤进"二进制,但它的影响最终必以某种形式进入机器状态(寄存器/内存), 而且进入点是良定义的、局部的、可静态分析的。
5.1 端到端架构
图 2:Xkernel 端到端工作流。离线阶段(xk-build)通过二进制 diff + 符号执行建立全局作用域表;
在线阶段(xk-gen → xk-load)由 Xk-runtime 加载 eBPF 策略并管理 SIE 间接执行。
5.2 核心概念:Critical Span (CS)
CS 是常量进入机器状态的单入口、单出口的指令序列——从贡献符号状态表达式的第一条指令开始, 到结果状态首次被消费或基本块结束时结束§3.4.1。
5.3 编译器变换的"魔法消失术"
源代码 #define V 5 在二进制中可能根本不出现字面量 5§3.3.1:
图 3:同一段源码用 V=5 编译时是 add eax, 5,V'=10 时变为 add eax, 10,
V''=17 时因 17=2⁴+1,编译器把它转成 lea eax, [eax+eax*4+1]——即 eax ← 17·eax。
源码值 V 并不直接出现在二进制中,必须通过符号执行恢复"等价 IV"。
5.4 符号状态表达式:从二进制反推语义
Xkernel 的解法是二进制差分 + 符号执行§3.3.2:
- 在源级别修改 perf-const,重建两个内核
- 用 diff 驱动符号执行识别"种子指令"(两版二进制指令不同处)
- 前后向探索直到符号状态收敛到不动点
- 通过第三个变体插值出 IV 与源码值 V 的线性映射
IV = a·V + b
5.5 合成间接:三种情况
符号状态表达式一旦得到,就可以针对 CS 设计"覆盖"合成代码。论文把情况分为三种§3.4.2:
图 4:三种合成情况。(a) 受影响寄存器在 CS 内未被重写,仅在出口后插入一次赋值; (b) 被可逆操作覆盖,合成逆逻辑作为更新的一部分; (c) 被不可逆操作覆盖,生成"双位置":修改前捕获原值,CS 后恢复。 实测仅 3/367 个 CS 需要情况 (c)§6.1。
5.6 关键性质总结
| 性质 | 由谁保证 | 对比 KLP |
|---|---|---|
| 版本原子性 | 符号状态表达式 + CS | KLP 仅有"按线程版本原子性" |
| 副作用安全 | Safe Span (SS) 封装 + 自收敛机制 | 缺失 |
| 多线程全局一致性 | 入口/出口 kprobe 引用计数 | 仅依赖 stop_machine,停止所有线程 |
| 转换时间 | 中位数 2.8ms(CS 单位) | 中位数 30.4ms + 7min 补丁生成 |
6. 副作用安全:从版本原子到全局一致
仅保证"旧值/新值切换瞬间不撕裂"是不够的——内核线程可能仍持有依赖旧值的运行时状态。 Xkernel 引入 Safe Span (SS) 概念,把"何时切换安全"从时间问题转化为空间问题§3.5。
6.1 为什么版本原子性不够
考虑如下控制流§3.5:
// f() 与 g() 都消费 perf-const
f() {
CS1(); // 受旧值 v 影响
g();
CS2(); // 受旧值 v 影响,但若在转换后执行则会用新值 v'
}
g() {
CS3(); // 不依赖 f 的状态,但也处于 f() 栈内
return;
}SCENARIO
仅看 CS1 / CS2 之间的版本原子性是不安全的——CS3 虽不依赖 f 的状态,但调用栈正穿过 f()。 Xkernel 通过 SS 显式封装这种传递依赖关系。
6.2 Safe Span 的形式化
含义:所有线程的 PC 都不在任何 SS 内部时,转换 v→v' 是安全的§3.5.1。
图 5:SS 是单入口、多出口的程序切片。任何传递流依赖 perf-const 的指令必须被包含在 SS 中。 一旦执行离开 SS,无线程保留对旧值的依赖,转换即可发生。
6.3 自收敛转换机制
SS 边界处插入 kprobe 作为"监视器"。仅初始化时调用一次 stop_machine 扫描所有运行线程的栈,
之后参与线程在跨越 SS 边界时自然自收敛并更新引用计数§3.5.2:
图 6:自收敛转换时序。初始扫描建立引用计数(线程 a 处于 SS1,线程 b 处于 SS2)。 当 a 退出 SS1 减少计数,b 退出 SS2 减少计数,归零时转换安全点到达。
6.4 嵌套 SS 的处理
若两个 SS 嵌套或重叠,则合并为更大的 SS。转换期间若某线程深陷另一 SS 的调用栈中,
入口 kprobe 会检测到并继续执行,进入另一 SS 时重试。这种设计避免了无限制的 stop_machine§3.5.2。
"Xkernel goes beyond version atomicity to guarantee side-effect safety— a property notably absent in existing kernel update mechanisms." — 论文摘要
7. 可编程策略平面:Xk-tune
SIE 是机制,Xk-tune 是策略。Xk-tune 是嵌入到 eBPF 事件模型中的 C-类 DSL,
用户通过 xk-gen 工具生成存根,在其中编写调优逻辑,再由 xk-load 加载§3.6。
7.1 最小 API
typedef const struct xk_ctx * xk_handle_t;
#define XK_TUNE(unique_name, perfconst_id, args...)
long xk_set(xk_handle_t xk_ctx, u64 val);
bool xk_transition_done(xk_handle_t xk_ctx);xk.h
两个调用构成完整契约:xk_set 写入新值;xk_transition_done 让策略等待转换完成(强制安全门)§3.6。
7.2 完整示例:TCP CUBIC HyStart 调优
XK_TUNE(tcp_hystart, "net/ipv4/tcp_cubic.c:L349:3:0") {
// 1. 安全保护门:未完成转换则放弃本次策略
if (!xk_transition_done(xk_ctx)) return 0;
// 2. 用户策略逻辑:仅当 RTT ≥ 80ms 时将缩放因子设为 1
struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx);
struct bictcp *ca = inet_csk_ca(sk);
u32 cur_rtt = BPF_CORE_READ(ca, curr_rtt);
if (cur_rtt >= 80000) xk_set(xk_ctx, 1);
return 0;
}XK_TUNE
7.3 转译与注入
每个 Xk-tune 被转译为对应 CS 的 eBPF kprobe。eBPF 验证器会先做安全性检查;
Xkernel 进一步暴露 sie_write_kernel 作为唯一的内核状态写通道(BPF kfunc)§3.6。
7.4 事务原子性
多个 Xk-tune 可捆绑到单个文件作为原子事务:要么全部加载生效,要么全部回滚。 每个 perf-const 最多属于一个活跃事务,简化了多常量协同调优的并发模型§3.6。
7.5 高级模式:应用感知 + 即席启发式
论文展示了两个更精妙的模式§5.2:
- 应用感知:RocksDB 通过 eBPF map 向前台与压缩线程传递 hint,Xk-tune 区分对待调优目标。
- 即席启发式:用
kretprobe/blk_attempt_plug_merge跟踪连续失败合并次数, 当 ≥ 16 时将 BLK_MAX_REQUEST_COUNT 设为 1——这是部署后才能发现的策略,无法硬编码到源码。
8. 案例研究:五个子系统,五种价值
论文在五个 Linux 子系统上端到端验证了 Xkernel 的实用性,覆盖了存储、中断、内存、NUMA、网络§5。 案例之间不仅是"再调一个常量",而是展示了 Xkernel 启用的调优策略谱系。
8.1 案例总览
| 案例 | Perf-const | 子系统 | 默认值 | 调优机制 | 关键收益 |
|---|---|---|---|---|---|
| Case-1 | BLK_MAX_REQUEST_COUNT |
存储(块层) | 32 | 适应硬件设备 + 负载模式 | HDD 写 54×;NVMe 吞吐 1.2× |
| Case-2 | MAX_SOFTIRQ_RESTART |
CPU(中断) | 10 | 在尾延迟与 CPU 利用率间权衡 | 最差延迟 560μs → 149μs(-22% CPU) |
| Case-3 | SHRINK_BATCH |
内存(回收) | 128 | 控制内核内部维护行为 | 值 ≤ 24 显著降低抖动延迟 |
| Case-4 | NR_MAX_BATCHED_MIGRATION |
内存(页迁移) | 512 | 用硬件可观测性推理 | 尾延迟 vs TLB shootdown 权衡 |
| Case-5 | HYSTART_DELAY_[MAX,MIN,factor] |
网络(TCP CUBIC) | [16, 4, 3] | 集体调优多个 perf-const | 长 RTT 流 P99.99 FCT -81% |
8.2 各案例详细解读
问题:HDD 需要攒批以合并相邻请求,NVMe 攒批反而引入额外延迟。
Xkernel 调优:通过单一 Xk-tune 程序同时为不同硬件/负载分配不同值——HDD 顺序 FIO 取 128,NVMe + RocksDB 随机取 1,其他工作负载保留默认值。
问题:该常量限制软中断处理程序在一次迭代中可重运行的次数。增大改善 CPU 利用率但放大尾延迟。
实验:4 节点 25 Gbps 集群,cyclictest 测延迟敏感负载 W_l,并发吞吐型负载 W_t。
问题:该值自 2005 年来固定为 128。Linux 为 43 个 slab 对象实现 shrinker,但共享同一批大小常量。
场景:使用 zswap-shrinker,周期性写/重写大匿名 mmap 区域(模拟有内存预算的数据分析)。
附加价值:Xkernel 允许通过检查调用者名称为不同 shrinker 自定义批大小——同一 perf-const 在不同上下文中取不同值。
问题:跨 NUMA 节点迁移的页面批量大小(2023 年引入,默认 512,控制 TLB shootdown 与页迁移摊销成本)。
实验:一组线程反复访问 NUMA 节点热数据,另一组持续迁移热页。
问题:TCP CUBIC 的 HyStart 机制用三个 perf-const 决定是否退出慢启动。高 RTT 下过于敏感(过早退出),低 RTT 下过于保守(延迟退出)。
优化方法:先用微基准测试理解不同 RTT 下的缩放因子;将 HYSTART_DELAY_MAX 从 16ms 改为 32ms;动态调整长 RTT 流的缩放因子(SF=1 vs SF=3)。
图 7:五个案例的关键性能提升幅度对比(取自论文 §5.1 报告数据)。 注意:每条柱的"提升"在原文中度量方式不同(吞吐、延迟、FCT 等),数值不可直接线性比较,但已对齐到相对量级。
9. 实现与评估
Xkernel 的实现规模是工程上"克制"的:约 1.7K 行内核 C + 11K 行 Python。 评估覆盖 140 个 perf-const,覆盖率 99.3%§6。
9.1 实现规模与工具链
| 组件 | 语言 | 代码量 | 职责 |
|---|---|---|---|
xk-runtime(内核模块 xk-sie.ko) | C | ~1.7K 行 | 运行时:BPF 加载、转换管理、引用计数 |
| 工具链 | Python | ~11K 行 | CS / SS 静态分析、Xk-tune 生成 |
| 符号执行引擎 | Python | ~5K 行 | CS 分析(驱动二进制 diff) |
| SS 分析 | C++(LLVM pass) | — | 在内核位码上做瘦切片 |
9.2 评估规模
- 评估机器:CloudLab,128GB RAM,28 核 Intel Xeon Gold 5512U (2.1 GHz),两块 800GB NVMe-Gen4 SSD
- 评估对象:140 个 perf-consts,来自四个 Linux 子系统(存储、内存、网络、CPU)
- 支持率:139/140 = 99.3%(唯一不支持的因 Kprobe 限制)
- 覆盖源码形式:宏、字面量、静态整数
9.3 Critical Span 的分布
图 8:140 个 perf-const 共有 367 个 CS。48% 映射到单一 CS,86% 少于 5 个;
长尾来自内联(如 DEF_PRIORITY 16 个、NFS4_POLL_RETRY_MAX 17 个)。
367 个 CS 中 82 个的符号值 IV 与源码值 V 不同,Xkernel 全部正确恢复。
仅 3 个 CS 需要"双位置"处理不可逆更新。
9.4 CS、SS、函数的大小对比
图 9:CS 极小(多数单条指令,最长 7 条),SS 中位数 10 条但有 ~8K 长尾。 函数远大于 SS,但安全保证弱于 SS——这正是 SIE 选择 SS 而非函数作为作用域单位的原因。
9.5 SIE 的运行时开销
图 10:基线 946 周期 / 操作(JMP 优化 kprobe + 全部 Xkernel 操作 O1–O4 累计 +25%)。 INT3 kprobe 开销高得多(基线 2711,+187%)。开销主导来自 Kprobe 机制本身, Xkernel 引入的额外开销很小。
9.6 触发频率 vs 相对开销
图 11:io_uring 异步写 /dev/null 工作负载。每操作 0μs 额外计算时 SIE 致 15% 减速; 5μs 时 5%;10μs 时 2%;≥20μs 时 < 1%。即每秒触发数百万次时开销可预测且可忽略。
9.7 多 kprobe 并发影响
图 12:Redis + YCSB / Facebook ETC 工作负载。32 个 SIE kprobe 时吞吐下降 ≤ 4%; 128 个时下降 7–14%,IPC 下降约 6%。证明可同时调优大量 perf-const,开销适中。
9.8 策略更新时间
图 13:策略更新由 BPF 验证、跳转优化、Kprobe 注册三部分组成。Kprobe 注册主导成本。 即使对有 15 个 SS 的复杂 perf-const,更新时间上限 542ms——满足毫秒级设计目标。
9.9 Xkernel vs KLP:转换时间对比
图 14:TCP 后端 perf-const,iperf3 × 128 流。中位数端到端延迟:Xkernel 2.8ms, KLP 30.4ms + 7min 补丁生成。CS 是比函数更高效的转换单位。
9.10 副作用安全保证的代价
图 15:按线程副作用安全 < 10ms;全局一致性下随并发度增加,最大 144ms(16 线程)。 SS 大小增加也延长转换时间——但即使是综合最坏情况,仍远低于 KLP 的端到端延迟。
9.11 离线分析成本
每个 perf-const 一次性成本:
- 两个内核编译(并行 56 线程):约 7 分钟
- 符号执行 + CS/SS 构造:平均 11 ± 20 分钟,最复杂 124 分钟
- 合计平均 18 分钟/perf-const
- 可并行(spot instances)且作用域表可跨同版本内核二进制复用
10. 讨论、局限与展望
Xkernel 优先考虑安全性而非完整性;它的边界、它的演化方向、它与 AI Agent 的结合是值得讨论的三个问题§7。
10.1 适用边界
- 不支持直接改变内核内存布局的常量(如数组大小、结构体填充)——通过 DWARF 调试信息(
pahole)可靠检测布局变化。 - 可检测并拒绝离线分析中发现常量在某二进制中不存在的死代码消除情况。
- CS 通常是无锁、阻塞原语或内存屏障的短序列,Xk-tune 改变具体化时保留原始并发语义。
- Kprobe 机制提供原子插入,本身具备良好并发安全。
10.2 选择"好"的值
Xkernel 不强加任何内置边界(寄存器宽度等架构约束除外)。边界属于性能语义而非 SIE 机制—— 用户可在 Xk-tune 中编码范围检查、设备特定约束、RFC 定义等。
10.3 维护性
作用域表绑定到精确的内核源、编译器版本和构建配置。假设编译器版本与构建配置可用 (定制内核固有;开箱即用内核可从官方源获取)。Xkernel 不限于内核树内代码, 还支持有源可加载内核模块和供应商驱动,但每个作用域表条目绑定到特定模块版本, 重建后必须重新生成。
10.4 与 AI Agent 的结合
论文 §5.2 与 Microsoft Research 的文章都强调了 Xkernel 作为AI Agent 操作系统接口的潜力§5.2:
"当调优接口是可编程、有作用域、经过验证、毫秒级生效的,那它的价值便不再局限于人工操作, 而可以成为 AI agent 安全操作的接口。Agent 可以在线观测 workload(Xkernel 兼容 eBPF, 可与 eBPF 观测体系结合)、在线生成并部署调优代码,为每个 workload 和每套硬件持续搜索特化的最优配置, 安全机制则确保整个过程不会破坏系统的正确性和稳定性。" —— Microsoft Research OSDI'26
10.5 向用户态泛化
SIE 的核心思想——捕获常量进入状态的精确边界、合成更新代码、封装安全转换—— 并非内核特有。论文暗示该方法可泛化到数据库等用户态系统软件, 系统性地增强其可调性与可特化性。这对云原生时代"一份代码服务多种 SLO"的需求具有深远意义。
10.6 局限与开放问题
- 识别 perf-const、推导影响边界需较强系统分析能力
- 复杂内核路径中并发、锁、缓存一致性、硬件差异可能带来额外验证成本
- 常量组合调优的安全分析仍是开放问题——单独安全不代表组合安全
- 自动发现值得调优的 perf-const(候选排序)
- 与在线性能反馈形成闭环调优
- 扩展到更多内核版本、架构和生产 workload
- 回滚机制、变更记录、效果观测自动化
- 向用户态(数据库、运行时)推广
10.7 结语
"代码生成不再只是运行在系统之外的辅助工具,而有机会成为系统自身的一部分。" —— Microsoft Research
Xkernel 把"运行时调参"从一种"妥协的运维手段"提升为"有边界、有记录、有反馈的内核机制"—— 它与 Kconfig、sysctl、live patching 一道构成完整的内核调优谱系,但首次让"运行时"和"可证明"这两个长期矛盾的特性共存。
引用与数据来源
- 主论文:Chen, Z., Zhang, W., Tang, Y., Shu, R., Ren, F., Xu, T., & Liu, J. (2026). Xkernel: Principled Performance Tunability of Operating System Kernels. Proceedings of OSDI 2026. arXiv:2512.12530v2. arXiv:2512.12530
- USENIX 会议页面: OSDI'26 Presentation
- Microsoft Research 解读: OSDI上新文章
- 开源实现: github.com/xkernel-org/Xkernel
- 论文内部引用: Sysctl [77]、Sysfs [54]、Live Patching [1,7,10,22,23] 等详见论文 §8 Related Work。
本报告所有数据均直接来源于上述论文与官方解读。除非特别说明,"图 N"指本报告自绘的可视化,
"§X.Y"指主论文中对应章节。所有性能数据均在原文报告的实验环境中测得。