本期检索说明

先读取 content/collections/deep-radar 截至 2026-10-01 的全部原文链接,并按 URL、标题与机制去重。最近 24 小时找到两项同时给出实测、完整源码差异与原理链路的新材料:HotSpot Thread-SMR 把每次线程增删触发的全线程 hazard-pointer 扫描改为有上限的批量回收;rustc 在单态化阶段用类型标志证明 generalization 是 no-op 后直接返回。Kotlin、Zig 与 Linux 的新候选没有同时满足三条证据红线,本期不凑数。

两项 PR 截稿时都仍在评审/合入队列中,本文评价的是公开 patch、复现与性能系统结果,不把它们写成已发布能力。HotSpot 作者只公开了定向复现的峰值改善,没有完整参数矩阵;Rust 则同时公开了定向 wall-clock 与全局 rustc-perf,后者还包含 RSS、cycles 和 bootstrap 的负向数据。

主题 原始发布日期 一手来源与交叉验证 截稿状态 推荐强度
Thread-SMR 批量回收 hazard pointers 2026-10-01 20:05(中原标准时间) OpenJDK PR #33166 / 完整 HotSpot patch / JDK-8307970 复现 / tier1–3 开放评审,尚未合入 强烈推荐,重点看扫描摊销与线程删除安全证明
rustc generalization no-op 快路径 2026-10-01 22:52(中原标准时间) Rust PR #163607 / generalize.rs patch / 定向 UI 用例 / rustc-perf 已批准并进入 bors 队列 强烈推荐,重点看 TypeFlags 与局部/全局 benchmark 差异

01 · JVM:Thread-SMR 不必为每次线程启动扫描所有 hazard pointers

原文与日期: fbredberg,2026-10-01 20:05(中原标准时间);OpenJDK PR #33166、完整源码 patch 与 JDK-8307970。

为什么值得读: HotSpot 每次启动或退出 Java 线程都会发布新的 ThreadsList 并退休旧列表。旧实现每退休一个列表,就遍历所有 JavaThread 的 hazard pointer 来判断哪些列表仍被 ThreadsListHandle 保护;空闲线程越多,这个扫描越贵,Thread.start() 的成本会随已有线程数增长。这是一个很典型的“安全回收协议正确,但把全局扫描放在高频局部事件上”的扩展性问题。

核心技术结论: 补丁把新增线程时的回收扫描延迟到两个阈值之一触发:累计退休 16 个 ThreadsList,或退休列表占用达到 4 MiB。删除线程仍强制扫描,但顺便判断待删 JavaThread 是否还出现在任何受保护的退休列表中;若没有,就设置 _smr_delete_is_safe,让后续 wait_until_not_protected() 直接返回。若 _to_delete_list == nullptr,也能证明不存在可保护该线程的旧列表并跳过再次扫描。

C++
if (thread_to_delete == nullptr) {
  _retired_since_reclaim_cnt++;
  _retired_since_reclaim_mem += threads->size_in_bytes();
  if (_retired_since_reclaim_cnt < 16 &&
      _retired_since_reclaim_mem < 4*M) {
    return;
  }
}

if (thread_is_safe_to_delete) {
  thread_to_delete->set_smr_delete_is_safe();
}

最有价值的实验、源码与 benchmark 细节: 作者运行 JDK-8307970 附带的 ThreadStart 复现;随空闲线程数变化,补丁让线程启动最高约快 63%,等价于启动耗时最高下降约 39%。这两个百分比不是同一分母:若新耗时为旧耗时的 61%,则旧/新约为 1.64×。补丁已通过 tier1–3,但 PR 没有公开完整的线程数—耗时表、硬件配置或置信区间,因此不能把峰值外推为所有线程创建负载。

源码层面的关键是一次扫描承担三件事:回收未受保护的退休列表、确认待删线程是否仍被旧列表包含、更新 _smr_delete_is_safe。ThreadsList::size_in_bytes() 同时把对象本体、指针数组和 null terminator 纳入 4 MiB 阈值,避免只有“16 次”而没有内存上限。回收仍在 Threads_lock 或 safepoint 保护下进行,真正的安全条件没有放宽;变化只是把新增线程路径的扫描从每次一次摊销为最多 16 次一次,并复用删除路径已经付出的扫描成本。

必须保留的风险面是内存与尾延迟:批量化意味着最多暂留 15 个列表,4 MiB 阈值提供了上界;触发阈值的那次启动仍承担完整扫描。_retired_since_reclaim_* 在 Threads_lock 下更新,所以不需要额外原子操作,但未来若改变锁域,这个隐含不变量必须重新审计。

适合的工程师背景: 熟悉 HotSpot 线程生命周期、RCU/hazard pointer、Safepoint,或正在排查“大量常驻线程导致新线程启动越来越慢”的 JVM 运行时工程师。

预计阅读收益: 约 30–45 分钟;能学到如何把全局安全扫描摊销到有内存上限的批次、如何复用一次扫描完成对象回收与线程删除证明,以及如何区分吞吐峰值与触发阈值的尾延迟。

02 · Rust:单态化阶段没有待泛化内容,就不要递归遍历类型

原文与日期: lcnr,2026-10-01 22:52(中原标准时间);Rust PR #163607、完整源码 patch 与 rustc-perf 对比。

为什么值得读: rustc 的 generalization 会遍历类型,把推断变量、自由区域、placeholder 和非 rigid alias 转成当前推断上下文可接受的形式。但进入 monomorphization 后,类型通常已具体化,这个遍历经常什么也不改。递归/大型类型把一个语义 no-op 放大成明显编译时间,issue-91949-hangs-on-recursion.rs 正是极端样本。

核心技术结论: 补丁把确实需要 generalization 的条件编码成编译期 TypeFlags 常量:HAS_FREE_REGIONS | HAS_INFER | HAS_PLACEHOLDER | HAS_NON_RIGID_ALIAS。Generalizer::tys 在访问 cache、递归关系或复制类型结构前先调用 has_type_flags;四类标志都不存在时直接 Ok(t)。这不是为某个具体 TyKind 写白名单,而是复用 rustc 类型驻留时维护的汇总位图,让快路径随嵌套结构自动成立。

Rust
const NEEDS_GENERALIZATION: TypeFlags = TypeFlags::from_bits(
    TypeFlags::HAS_FREE_REGIONS.bits()
        | TypeFlags::HAS_INFER.bits()
        | TypeFlags::HAS_PLACEHOLDER.bits()
        | TypeFlags::HAS_NON_RIGID_ALIAS.bits(),
).unwrap();

if !t.has_type_flags(NEEDS_GENERALIZATION) {
    return Ok(t);
}

最有价值的实验、源码与 benchmark 细节: 定向 UI 用例在相同分支上从 47 秒降至 7.8 秒,耗时下降约 83.4%,约为 6.03× 加速。官方 rustc-perf 给出更可迁移的全局口径:115 个 primary 改善样本的 instructions:u 平均下降 0.5%,范围为 0.1%–4.4%,没有显著指令回退;153 个 secondary 改善样本平均下降 1.4%,最大 15.8%。

负向数据同样重要:Max RSS 有 5 个 secondary 样本回退,平均 3.9%、范围 2.8%–4.8%;cycles 虽有 3 个 primary 样本平均改善 3.2%,却有 5 个 secondary 样本回退 2.3%–12.2%。bootstrap 从 490.365 s 到 491.412 s,慢 0.21%;artifact 从 406.38 MiB 增至 409.40 MiB,增加 0.74%。因此合理结论是“删除了广泛存在的冗余类型遍历,并修复极端退化”,而不是“所有 Rust 构建快 6 倍”。

源码只改 13 行,却依赖一个关键不变量:所有 generalizer 会产生动作的类型特征都必须被 NEEDS_GENERALIZATION 覆盖。漏掉标志会把需要重写的类型错误地原样返回;多列标志只会损失性能。将语义条件集中成常量,比在遍历器内部逐分支短路更容易审计,也能让 TypeFlags 的缓存成本在多个编译器阶段复用。

适合的工程师背景: 熟悉 rustc infer/trait solver、类型驻留与 monomorphization,或维护编译器中“先用汇总元数据判空,再递归遍历”快路径的工程师。

预计阅读收益: 约 30–45 分钟;能学到如何用预计算类型标志证明遍历是 no-op、如何用极端用例定位复杂度放大点,以及如何用 rustc-perf 约束对定向 6× 结果的表述。

中国大陆 ToC 硬件价格观察

数据口径

窗口为 2026-09-03 至 2026-10-02,单位人民币,六类硬件固定同一 SKU。今天通过公开比价页的实时渲染结果复核到 CPU、GPU、主板、HDD、SSD 五类报价;DRAM 页面仍明确显示“暂无报价”,因此不新增点。重复价格作为真实采样保留,用来区分“已复核横盘”和“未取得数据”。SSD 只采用当前 2TB 规格的全网比价栏,不采用跨容量聚合的“¥819 起”。

中国大陆六类 PC 硬件公开价格事件

类别 10 月 2 日可复核价 30 日窗口内真实走势 建议
CPU Ryzen 7 9800X3D,京东 ¥2,694 9/3 ¥2,599 → 9/9 ¥2,449 → 9/23–24 ¥2,579 → 10/1 ¥2,699 → 10/2 ¥2,694 观望;单日仅回落 0.19%,仍比窗口低点高约 10.0%
GPU MSI RTX 5070 VENTUS 3X 12G,亚马逊中国 ¥4,464.34 9/7–10/2 多次实时复核均为 ¥4,464.34 刚需可比价后入手;单一渠道横盘不等于全市场没有促销
主板 ASUS TUF B850M-PLUS WIFI7,天猫 ¥1,299 9/3–10/2 多次复核均为 ¥1,299 刚需可入;公开最低价稳定,但下单前核对店铺与售后
DRAM 暂无报价;最后可复核 9/9 ¥3,900 9/3 ¥3,900 → 9/5 ¥3,860 → 9/6–9/9 ¥3,900 观望;固定 SKU 缺价,不用其他容量、颗粒或时序替代
HDD IronWolf Pro 8TB ST8000NE001,i百联 ¥1,849 9/3–10/2 多次复核均为 ¥1,849 容量刚需可买;先核对型号、五年保修与数据恢复服务
SSD ZHITAI Ti600 2TB,京东 ¥1,799 9/23–10/2 多次复核均为 ¥1,799 观望或确认结算价后入手;当前可比价横盘,聚合栏可能滞后

价格来源: 9800X3D、MSI RTX 5070 VENTUS 3X、ASUS TUF B850M-PLUS WIFI7、Kingston FURY DDR5-6000 32GB、IronWolf Pro 8TB、ZHITAI Ti600 2TB。

判断依据

CPU 是今天唯一变价 SKU,公开最低报价从 ¥2,699 回落到 ¥2,694,单日仅下降 0.19%,不足以扭转此前两次上行;相对 9 月 9 日低点仍高约 10.0%,没有数据支持“继续下跌”。GPU、主板、HDD 与 SSD 只是同一公开渠道再次横盘,不能外推为整个中国零售市场稳定。SSD 页面头部显示跨容量聚合的“¥819 起”,但 2TB 当前规格的全网比价仍为 ¥1,799,两种口径不能混用。DRAM 固定 SKU 继续缺价。本期购买建议只依据可复核价格序列,不引用未核实的新品或产能传闻。

其它你可能关心的

本期结论

两篇材料都在用“廉价证明”移除高频的全局工作:Thread-SMR 用数量和内存双阈值证明何时值得扫描,并把删除安全判断合并进同一次 hazard-pointer 遍历;rustc 用预计算 TypeFlags 证明一个类型不可能需要 generalization。前者峰值把线程启动耗时压低约 39%,后者让极端用例从 47 秒降至 7.8 秒,且全局指令数没有显著回退。可迁移的方法不是盲目批处理或增加 fast path,而是让快路径携带明确的内存上界、语义位图和慢路径回退,再用负向指标检查代价是否只是被转移。