本期检索说明
先读取 content/collections/deep-radar 截至 2026-10-03 的全部原文链接,并按 URL、标题和实现机制去重。最近 24 小时找到两项同时给出实测、完整源码差异和原理链路的新材料:Rust 标准库为 str::Chars 补上反向分块跳过;Kotlin 标准库把 Sequence.filterIndexed 从三层组合改成单层、有原始 Int 计数器的 iterator。Java、Zig 与 Linux 的新候选没有同时满足三条证据红线,本期不凑数。
两项 PR 截稿时都仍处于开放评审,benchmark 为作者在 PR 中公开的可复现结果,尚不能等同于合入后的跨平台保证。本文评价的是源码 patch、测试设计和已公开数据,不把它们写成已发布能力。
| 主题 | 原始发布日期 | 一手来源与交叉验证 | 截稿状态 | 推荐强度 |
|---|---|---|---|---|
Rust Chars::advance_back_by 反向分块计数 |
2026-10-04 06:14(中原标准时间) | Rust PR #163726 / 完整 core patch / 新增 benchmark 与边界测试 / 标准库 API 文档 | 开放评审,尚未合入 | 强烈推荐,重点看 UTF-8 边界修正和小规模反例 |
Kotlin Sequence.filterIndexed 单层 iterator |
2026-10-03 23:22(中原标准时间) | Kotlin PR #8662 / stdlib 与生成器 patch / Sequence 回归测试 / 官方 API 文档 | 开放评审,尚未合入 | 推荐,重点看 allocation 是否真落在中间对象 |
01 · Rust:反向跳过字符不必逐个解码 UTF-8
原文与日期: CarloTUM,2026-10-04 06:14(中原标准时间);Rust PR #163726、完整源码 patch 与 str::Chars 官方 API。
为什么值得读: Chars 的正向 advance_by 已经会按 32 字节块统计 UTF-8 起始字节,但 DoubleEndedIterator 没有覆盖默认的 advance_back_by。于是 chars().nth_back(n)、chars().rev().skip(n) 和 .rev().nth(n) 仍逐字符调用反向解码器。抽象完全对称,执行路径却不对称;这类遗漏很容易藏在标准库默认实现下面。
核心技术结论: UTF-8 continuation byte 总是满足 10xxxxxx,所以一个块中“不是 continuation byte”的字节数就是字符起点数。新实现从尾部把底层字节切成 32 字节块,整块统计起始字节并扣减 remainder;块级阶段结束后,再逐字符处理不足一块的余数。这样大步跳过的复杂度仍与字节数相关,但把每字符的分支和 Unicode scalar value 组装换成了紧凑的字节分类。
const CHUNK_SIZE: usize = 32;
let mut chunks = self.iter.as_slice().as_rchunks::<CHUNK_SIZE>().1.iter().rev();
while remainder > CHUNK_SIZE && let Some(chunk) = chunks.next() {
bytes_skipped += CHUNK_SIZE;
let mut start_bytes = [false; CHUNK_SIZE];
for i in 0..CHUNK_SIZE {
start_bytes[i] = !utf8_is_cont_byte(chunk[i]);
}
remainder -= start_bytes.into_iter().map(|x| x as u8).sum::<u8>() as usize;
}最容易写错的是块边界。若已跳过的尾部字节恰好从一个多字节字符的中间开始,该字符的 leading byte 不在已统计块内,continuation bytes 也就不该从 iterator 中删除。patch 因此从 len - bytes_skipped 向后检查,遇到 continuation byte 就把 bytes_skipped 减一,直到回到字符边界;这不是边角补丁,而是分块算法保持 iterator 语义的关键不变量。
最有价值的实验、源码与 benchmark 细节: 作者在 x86-64 上用 ./x bench library/coretests --test-args chars_advance 跑俄文大文本。反向跳过 1000 个字符从 980–1062 ns 降到 106–166 ns:按区间最保守组合约 5.9 倍,最好组合约 10.0 倍;新路径已接近正向 advance_by(1000) 的 165–177 ns。跳过一个字符从 0.84–0.88 ns 降到 0.45–0.68 ns。
负向边界也很重要:跳过 10 个字符由 4.7–4.9 ns 变成 3.4–5.1 ns,区间重叠,不能宣称稳定变快。原因是 remainder >= 32 才进入块级路径,小步场景主要仍走原有逐字符循环;这说明优化目标是大跨度 nth_back/skip,不是所有反向迭代。
回归测试用 aé€😀b 与 ß中🦀 混合 1–4 字节字符,重复到跨越多个 32 字节块,再从六个不同的合法起点切片。对每个 n(还包含越过末尾的两个值),它比较新 advance_back_by(n)、nth_back(n) 与重复 next_back() 的剩余 as_str() 和错误余量。另一个日文长串测试专门跨过 33 个字符。这个测试矩阵比单纯断言最终字符更有价值,因为它直接验证分块后 iterator 内部切片仍落在 UTF-8 边界。
适合的工程师背景: 熟悉 Rust iterator、UTF-8 编码或标准库热路径,正在实现文本扫描器、反向 parser,或需要判断默认 trait 方法何时值得专门化的工程师。
预计阅读收益: 约 30–45 分钟;能学到如何把变长编码的字符计数降成字节分类、如何修复反向分块的字符边界,以及如何用小 n 的无收益数据限定优化范围。
02 · Kotlin:filterIndexed 的便利组合每个元素都在分配 IndexedValue
原文与日期: HamidRezaLS,2026-10-03 23:22(中原标准时间);Kotlin PR #8662、完整 stdlib patch 与 Sequence.filterIndexed 官方 API。
为什么值得读: 旧实现只有一行,却组合了 IndexingSequence → FilteringSequence → TransformingSequence。IndexingSequence 为每个被检查的元素创建一个 IndexedValue(index, value),随后 filter 读取它,最后 transform 又只取回 value。惰性没有消除分配;它只是把中间对象推迟到迭代时创建,并额外叠了三层 hasNext/next 委托。
核心技术结论: 新的 FilteringIndexedSequence 把 index 作为 iterator 内部的原始 Int 保存,直接调用 predicate(checkIndexOverflow(index++), item),并用 nextState = -1/0/1 表示未知、结束和已有候选。它仍保留 Sequence 的惰性、重复迭代时索引归零、null 元素与 take 提前结束语义,但不再 materialize IndexedValue。
private fun calcNext() {
while (iterator.hasNext()) {
val item = iterator.next()
if (predicate(checkIndexOverflow(index++), item) == sendWhen) {
nextItem = item
nextState = 1
return
}
}
nextState = 0
}patch 同时修改生成模板 libraries/tools/kotlin-stdlib-gen/.../Filtering.kt,而不只改生成出的 _Sequences.kt。这是标准库工程里非常可迁移的细节:若只修生成物,下次重新生成就会把优化覆盖掉。
最有价值的实验、源码与 benchmark 细节: 100,000 个元素、50% 选择率的实验中,堆分配从 4.85 MB 降到 2.45 MB,减少 2.40 MB、约 49.5%;单次延迟从 2.35 ms 降到 1.44 ms,缩短约 38.7%,按耗时比约 1.63 倍。分配没有归零,因为结果收集、iterator 和闭包等成本仍在;这也让数字比“零分配”口号更可信。
源码差异新增 55 行单层 iterator,并补了五组语义测试:索引严格为 0,1,2,3;空序列不调用 predicate;同一 Sequence 两次迭代均从索引 0 开始;null 元素可正确筛选;无限序列配合 take(3) 只求值五个元素并得到 0,2,4。其中 checkIndexOverflow(index++) 保留旧实现的溢出行为,避免为了速度悄悄改变极长序列的失败语义。
证据边界需要说明:PR 没附 benchmark harness 源码、warmup/迭代次数、JVM 参数和误差区间,因此 49.5% 的 allocation 方向可由源码结构直接解释,1.63 倍延迟则应视为作者样机结果,不能外推到短序列或 predicate 很重的业务。工程上最值得复测的是 N、选择率和 predicate 成本三维交叉,而不是只重复 100,000/50% 单点。
适合的工程师背景: 熟悉 Kotlin Sequence、JVM allocation profiling、标准库生成器,或正在审计“看起来优雅”的 iterator/stream 组合是否产生中间对象的性能工程师。
预计阅读收益: 约 25–35 分钟;能学到如何沿 Sequence 包装链定位真实 allocation、如何把组合算子融合成单层状态机,以及怎样用语义测试保护惰性和索引行为。
中国大陆 ToC 硬件价格观察
数据口径
窗口为 2026-09-05 至 2026-10-04,单位人民币,六类硬件固定同一 SKU。今天通过公开比价页的实时渲染结果复核到 CPU、GPU、主板、HDD、SSD 五类报价;DRAM 页面仍明确显示“暂无报价”,因此不新增点。重复价格作为真实采样保留,用来区分“已复核横盘”和“未取得数据”。SSD 只采用当前 2TB 规格的全网比价栏,不采用跨容量聚合的“¥819 起”。
| 类别 | 10 月 4 日可复核价 | 30 日窗口内真实走势 | 建议 |
|---|---|---|---|
| CPU | Ryzen 7 9800X3D,京东 ¥2,699 | 9/5 ¥2,599 → 9/9 ¥2,449 → 9/30 ¥2,679 → 10/1 ¥2,699 → 10/2–3 ¥2,694 → 10/4 ¥2,699 | 观望;重新回到窗口高位,较 9/9 低点高约 10.2% |
| GPU | MSI RTX 5070 VENTUS 3X 12G,亚马逊中国 ¥4,464.34 | 9/7–10/4 多次实时复核均为 ¥4,464.34 | 刚需可比价后入手;单一渠道横盘不等于全市场没有促销 |
| 主板 | ASUS TUF B850M-PLUS WIFI7,天猫 ¥1,299 | 9/5 ¥1,379 → 9/6–10/4 多次复核均为 ¥1,299 | 刚需可入;公开最低价稳定,但下单前核对店铺与售后 |
| DRAM | 暂无报价;最后可复核 9/9 ¥3,900 | 9/5 ¥3,860 → 9/6–9/9 ¥3,900 | 观望;固定 SKU 缺价,不用其他容量、颗粒或时序替代 |
| HDD | IronWolf Pro 8TB ST8000NE001,i百联 ¥1,849 | 9/5–10/4 多次复核均为 ¥1,849 | 容量刚需可买;先核对型号、五年保修与数据恢复服务 |
| SSD | ZHITAI Ti600 2TB,京东 ¥1,799 | 9/23–10/4 多次复核均为 ¥1,799 | 观望或确认结算价后入手;2TB 比价横盘,聚合栏可能滞后 |
价格来源: 9800X3D、MSI RTX 5070 VENTUS 3X、ASUS TUF B850M-PLUS WIFI7、Kingston FURY DDR5-6000 32GB、IronWolf Pro 8TB、ZHITAI Ti600 2TB。
判断依据
CPU 从昨日 ¥2,694 小幅回升至 ¥2,699,再次触及本窗口高位;相对 9 月 9 日低点 ¥2,449 已反弹 ¥250、约 10.2%,没有形成继续下跌信号。GPU、主板、HDD 与 SSD 只是同一公开渠道再次复核到相同最低价,不能外推为整个中国零售市场稳定。DRAM 固定 SKU 继续缺价,走势图保留真实空白尾段。SSD 页面头部仍显示跨容量聚合的“¥819 起”,但当前 2TB 规格的全网比价为 ¥1,799,两种口径不能混用。本期建议只依据可复核序列,不引用未核实的新品或产能传闻。
其它你可能关心的
本期结论
两篇材料都在处理“组合抽象的隐形税”。Rust 的默认反向 iterator 路径为每个字符解码,而 32 字节分块把 1000 字符跳过加速约 5.9–10.0 倍,同时用 continuation-byte 回退守住 UTF-8 边界;Kotlin 的一行组合为每个元素制造 IndexedValue 并穿过三层 iterator,单层状态机让分配下降 49.5%、延迟缩短约 38.7%。可迁移的方法不是一味手写循环,而是先找出抽象层真正重复的工作,再用边界测试和小输入负向数据约束专门化范围。