Daniel Lemire

37 篇内容

技术文章Daniel Lemire

Telling your number parser what to expect

文章介绍 fast_float 数字解析库新增的性能提示:针对分支预测失败带来的 15—20 周期开销,作者通过模板参数让调用者声明符号随机、数字较短或舍入模式固定,分别采用无分支处理、一次读取 8 字符和跳过舍入模式检查。提示不改变解析结果,但错误承诺 assume_round_to_nearest 可能导致结果错误。作者在 Intel Xeon 与 Apple M4 上对价格变动、账户余额、传感器读数、固定格式价格四类数据做吞吐基准,发现最佳提示组合随数据分布变化,错误提示会因增加指令而变慢。结论是提示用更多指令换取更少分支,只有在处理器确实频繁猜错时才值得使用,目前实现位于 PR 中。

推荐收录:文章不仅给出 fast_float 的 API 变更,还以分支预测、指令开销和四类数据基准解释了性能提示为何有效、何时反噬,并明确 assume_round_to_nearest 的正确性边界。适合高性能解析、C++ 基础库和低延迟系统开发者参考,其按数据分布选择优化策略、用基准验证取舍的方法可迁移;主要风险是提示依赖调用者对数据的先验假设,误用会降低性能甚至改变结果。

技术文章Daniel Lemire

A performance trap: when store forwarding fails

文章解释 store forwarding 失败为何会成为性能陷阱:写操作先进入 store buffer,后续 load 若与 store 同宽或完全落在其范围内可被转发;若 load 更宽或仅部分重叠,则需等待 store 写入缓存。作者用 C 示例展示单字节写后读 8 字节、4 字节写后读 8 字节等触发场景,并给出先在寄存器中读改写再整体写回的规避方式,同时提醒编译器可能消除冗余 reload。微基准覆盖 Xeon、EPYC、Graviton 与 Apple M4 Max,显示同地址 8 字节存取约 1 周期,宽 load 在 x86 上可达 14–19 周期,ARM 平台约 5 周期。结论适合用于微架构层面的性能诊断,但受具体 CPU 和编译器优化影响,不能直接外推到所有访问模式。

推荐收录:文章以可复现的 C 微基准和跨 CPU 周期数据,直观说明 store forwarding 失败的触发条件与代价,并给出寄存器读改写的规避方案。适合底层性能优化、C/C++ 系统编程和计算机体系结构读者,用于诊断宽 load 或部分重叠访问导致的意外停顿;但读者需注意结果依赖微架构和编译器,不能当作通用常数。

科研思考Daniel Lemire

Open source as a research method

文章围绕“开源作为一种研究方法”展开,作者以 simdjson、Eisel-Lemire 浮点解析算法和 simdutf 的演进为例,主张先写出可用代码、让真实用户使用并暴露问题,再以论文总结设计。作者引用 Stonebraker 关于数据库研究失去真实客户的判断,以及 Patterson 用非研究者是否采用成果衡量研究影响的观点,强调缺陷报告、对抗性输入、异构硬件和代码审查能提供比论文评审更严格的反馈。文中还给出 JSON 解析从数百 MB/s 提升到约 4.8 GB/s、浮点转换与 UTF-8 校验相继成为新瓶颈并被 Rust、Go、.NET、C++ 及主流运行时采用等证据。作者进一步认为,AI 降低了阅读陌生代码库和提交修复的门槛,可能促进而非削弱开源协作。其边界在于论述主要基于个人项目经验,对 AI 影响和开源研究普适性的判断仍偏经验性,缺少系统化评估。

推荐收录。文章用 simdjson、Eisel-Lemire 和 simdutf 的真实采用情况,具体说明“先构建、让用户提出问题、再形成论文”的研究路径,而非泛泛谈开源;其中将 pull request 与代码审查视为更严格同行评审的观点,对开源维护者、性能工程研究者和软件工程研究者有可迁移价值。需注意结论主要来自作者个人项目经验,读者应结合更系统的研究评价方法使用。

技术文章Daniel Lemire

In C++, = default and {} are not the same constructor

文章解释 C++ 中 `span() = default` 与 `span() {}` 并非等价:前者在首次声明时使类型保持 trivial,而后者是用户提供的构造函数。作者用包含指针、长度和尾指针的 span 结构展示,`= default` 配合 `{}` 值初始化会零初始化整个对象(含填充字节),`{}` 版本则不会。在循环构造 `box` 的微基准中,GCC 15/16 为 `= default` 版本生成临时对象和额外拷贝,导致约 1.73 ns/span 对 7.75–8.04 ns/span,慢四倍以上;GCC 14 和 clang 21 无明显差异。结论适用于关注 C++ 对象初始化语义和性能的代码,但属于特定编译器版本和微基准结果,需在目标工具链上验证。

推荐收录,因为文章用可复现的汇编差异和实测数据说明了 C++ triviality 与值初始化的隐蔽性能影响,GCC 15/16 下 `= default` 版本约慢四倍。适合 C++ 库作者、性能敏感后端开发者和编译器优化读者,其中对象初始化语义、基准方法和工具链差异分析可迁移到实际代码审查与性能验证中;主要风险是结论依赖编译器版本和微基准场景,不能无条件外推。

技术文章Daniel Lemire

Beating the compiler at signed 32-bit division

文章讨论 64 位处理器上有符号 32 位整数除法的优化。编译器对常量除数通常用乘法加移位,但当最优乘数需要 33 位时,会插入加回 x 的修正步骤;作者利用被除数绝对值不超过 2^31,把乘数当成 32 位无符号数并与有符号 32 位被除数做 64 位乘法,从而直接得到商,并给出乘数 c=ceil(2^s/d) 的选取依据和模板实现。实测在 Emerald Rapids 与 Apple M4 上,对 7、60、365 等需要修正的除数可缩短关键路径约 2 个周期,clang 吞吐提升超过 20%,但对 1000 这类无需修正的除数没有收益,M4 上甚至略慢。文章还把思路推广到运行时除数,用 mul128_s64_hi 的无分支实现更新 fastmod 0.2.0,避免随机符号导致的分支误预测。适用边界是正且非 2 的幂的常量除数或运行时除数库,性能收益依赖微架构与编译器。

推荐收录,因为文章不仅给出可复现的模板代码和数学条件,还用 GCC/clang 在 Emerald Rapids、M4 上的延迟与吞吐数据验证收益及无收益场景。适合编译器代码生成、底层性能优化和整数算法库的读者,其利用 64 位乘法空闲位消除修正步骤的思路可迁移到其他常量运算优化。

技术文章Daniel Lemire

Billion-query-per-second lookup tables in C++

文章讨论当字符串键在编译期已知时,如何用 C++ 完美哈希替代 std::unordered_map 完成高速查表。作者沿用 gperf 思路,用键长度和少量字符经关联表映射到槽位,并在 constexpr 阶段以贪心算法搜索无冲突参数;运行时只需一次哈希和一次比较。为加速键比较,文章把短字符串零填充后按 16 字节向量加载,用 shuffle 清除越界字节,并对接近页尾的地址走慢路径以避免越界访问。基准在 Apple M3 Max 上比较 HTTP 头等键集,显示每次查询约 1.3 ns/5 周期,较 gperf 快 3–6 倍、较 std::unordered_map 快 7–13 倍,M4 上 URL 协议查询超过每秒十亿次。该方法适用于键集固定且可编译期生成的场景,不适用于动态增删键;性能结论也依赖具体硬件、编译器和键分布。

推荐收录,因为文章不仅给出完美哈希的构造公式和 C++ constexpr 实现,还解释了向量化比较、页边界慢路径及与 gperf、Abseil、std::unordered_map 的实测对比。对编写解析器、协议分派或高频字符串查表的 C++ 工程师有直接迁移价值;但需注意其前提是键集编译期固定,动态键场景和跨硬件性能不能照搬。

工程实践Daniel Lemire

Redis now has compressed bitmaps (Roaring)

文章介绍 Redis 新增基于 Roaring 的压缩位图类型,并回顾传统 Redis 位图以普通字符串存储的机制与代价。传统位图按最大 offset 分配连续内存,稀疏集合会浪费大量空间,BITCOUNT、BITOP 等操作需扫描整个底层字符串。Roaring 根据数据分布自适应使用整数列表、普通位集或 run-length 编码,在稀疏或连续场景下减少内存并加速计数、交集与并集。作者在 Redis 合并提交上以 Intel Xeon 单核运行四类负载,对比字符串位图与 Roaring 位图,显示 Roaring 在部分场景明显更快,但并非总是更优,存在权衡。该功能为 opt-in,预计随 Redis 8.12 发布,可通过配置开启,TYPE 返回 bitmap,OBJECT ENCODING 返回 bitmap-roaring。

推荐收录,因为文章不仅说明 Redis 支持 Roaring 压缩位图,还解释了传统位图按最大偏移分配连续内存、扫描成本高的问题,并给出可复现的单核基准负载和性能对比。对使用 Redis 做集合统计、缓存或大规模稀疏数据处理的工程师有直接参考价值,同时提醒 Roaring 并非所有负载都更优,需结合实际数据分布权衡内存与速度。

工程实践Daniel Lemire

Parsing JSON at tens of gigabytes per second… in Python

Daniel Lemire 用 GH Archive 八小时 7.6 GB NDJSON、220 万事件做实测,统计新开 Pull Request 的仓库语言。方法是用 Python 3.14t 无 GIL 版本和 fastsimdjson 的 map_many,以 64 线程并行解析;每线程维护独立 Counter,最后合并,并通过 lazy=True 只创建访问字段的 Python 对象。单核下 lazy 版达 2.13 GB/s,明显快于标准 json 0.18、orjson 0.42、非 lazy 0.63 和 msgspec 1.29;64 线程下 lazy 版达 65.7 GB/s,7.6 GB 约 0.12 秒,约为单核 31 倍,并快于 msgspec 的 24.6 GB/s。结论是在特定库、无 GIL Python 和惰性解析条件下,Python 可达到数十 GB/s JSON 解析;但依赖 fastsimdjson、free-threaded 版本和内存中数据,且延迟与内存开销等边界未充分展开。

推荐收录:文章给出可复现基准、完整代码和与 json/orjson/msgspec 的横向对比,直接证据是 64 线程 lazy 解析 65.7 GB/s、约 0.12 秒处理 7.6 GB。它适合 Python 性能、数据管道和 JSON/NDJSON 处理读者,可迁移每线程累加器、惰性视图和并行基准方法;但方案依赖无 GIL Python 3.14t 与 fastsimdjson,需评估兼容性和内存开销。

技术文章Daniel Lemire

WebSocket servers in JavaScript: Node.js, Bun and Deno in 2026

文章用新基准重新比较 JavaScript WebSocket 服务器:Node.js 26 + uWebSockets.js、Bun 1.4.2 + Bun.serve、Deno 2.9.7 + Deno.serve,并以小型 C relay 为参照。作者先修正旧测试缺陷:JavaScript 客户端太慢,且 Bun 服务端把消息回给发送者,使往返消息数错误并夸大 Bun 优势。新测试改用 C 客户端,在 Intel Xeon Gold 6548N 上经 loopback 运行,服务端限单核、客户端另一核,三次重复结果稳定。结果为 C relay 约 5.4 万往返/秒,Node.js 约 4.9 万,Deno 约 4 万,Bun 约 3.7 万;Node.js p99 延迟也优于另两者。结论是 JS WebSocket 服务可接近 C 服务,Node.js+uWebSockets.js 当前最好,但仅限单连接 ping-pong,不能外推到多连接或生产负载。

推荐收录。文章不仅给出 Node、Bun、Deno 的具体吞吐与延迟数据,还诚实修正旧基准的客户端瓶颈和消息计数错误,并提供可复现代码,证据链完整。适合后端或实时通信选型、性能基准读者,可迁移价值在于提醒基准设计要控制客户端、消息路径与硬件边界;主要风险是单连接 ping-pong 结论不能代表多连接生产负载。

技术文章Daniel Lemire

Faster Python startup with lazy imports

文章介绍 Python 即将支持的 lazy import:在导入语句前加 lazy 后,模块名仅作占位符,真正使用该模块时才执行导入。作者用一个导入 json、csv、pandas 等十六个模块的玩具命令行工具,在 Python 3.15.0b4 上对比 eager 与 lazy 导入的启动耗时。结果显示,--version 路径从 295ms 降至 20ms,mean 路径从 296ms 降至 24ms,但 stats 路径仅从 299ms 降至 224ms,收益取决于实际用到的依赖。作者还提醒 lazy import 会把缺少模块的报错从启动时推迟到首次使用,可能深藏在函数或长时间运行的服务中。因此该特性适合优化启动路径,但需配合测试和错误处理。

推荐收录,因为它给出了可复现的基准数字和对照路径,不仅说明 lazy import 能显著降低 Python 启动开销,也指出收益受实际依赖影响,并明确错误延迟这一风险。对构建 Python CLI、服务冷启动优化或维护大型依赖树的读者,文中的一词语法改动、测量方法和适用边界可直接迁移到工程评估中。

工具笔记Daniel Lemire

Faster software linking with mold

文章记录 Daniel Lemire 使用 mold 链接器加速 Node.js 构建的基准测试。作者在同一台 Intel Xeon Gold 6548N 服务器和 GCC 14.3 环境下,对约 160 MB 的 node 可执行文件链接命令重复运行六次并取中位数,对比 GNU ld、GNU gold 和 mold 3.0.0。结果为:GNU ld 约 2.52 秒,gold 1.46 秒,mold 单线程 0.49 秒,8 线程 0.13 秒,128 线程 0.11 秒;多线程 mold 比 ld 快约 24 倍,比 gold 快约 14 倍,单线程也约为 ld 的 5 倍,8 线程已接近全部收益。作者还给出 -fuse-ld=mold 或 mold -run make -j128 的接入方式,并指出节省的链接时间只在频繁重建时显著,脚本与原始结果已公开。

推荐收录:文章给出了可复核的链接耗时数据、硬件与版本信息,并公开脚本和原始结果,能直接支撑链接器选型与构建加速判断。它适合需要频繁编译大型 C/C++ 或 Node.js 项目的开发者、构建/基础设施工程师,迁移价值在于用 mold 的 -run 或 -fuse-ld 替代默认链接器来缩短迭代反馈。局限是仅覆盖一个项目与单机环境,不深入链接器内部实现,结论需结合自身构建规模验证。

工具笔记Daniel Lemire

Ephemeral testing

文章提出一种新的软件质量验证方法——“临时测试”(ephemeral testing)。核心思路是不直接评估自己构建的库或组件,而是让 AI 代理在其之上快速搭建一个或多个一次性的上层应用并完成测试,借上层软件能否顺利运行来反推底层 API 设计的质量。作者认为这本质上是集成测试,区别在于上层代码用完即弃。干净 API、稳定不变量、清晰错误能让代理快速产出可用结果,而隐藏状态、意外默认值和文档缺失则导致大量补丁与失败,这些失败是对底层代码而非代理的反馈。该方法可更换不同代理、不同任务重复执行,作者已用它为未来功能做快速原型;边界是需要核心一定的稳定性,不能依赖“随时重建一切”。

推荐收录。它提出一个可迁移的测试实践:用 AI 生成的一次性上层应用暴露底层库的 API 设计缺陷,把集成测试与 AI 代理结合起来,适合负责库/组件设计与测试策略的开发者。不足是正文较短、缺少系统性验证,读者需自行判断其适用边界。

工程实践Daniel Lemire

Parsing compressed JSON at 40 GB/s

文章讨论 NDJSON/JSON Lines 大文件压缩后如何高速读取,并以 simdjson 为例。作者用 5 百万条、812 MB 合成数据统计 active 记录并汇总 admin 用户得分。核心是按行边界切分解压缓冲:gzip 单流受 32 KiB 窗口限制只能单线程解压,文中用一线程解压、多线程解析,达约 2.5 GB/s;zstd/lz4 每 256 KiB 在新行处切独立帧,线程可跳过帧头分工解压解析。64 线程下 zstd 达 40 GB/s、lz4 达 34 GB/s,约为 gzip 最佳方案的 16 倍。代价是 zstd 比 gzip 约大 6%,且合成数据重复度高,真实数据可能更慢;适合能控制写入格式的高吞吐数据管道。

推荐收录:文章给出代码、数据规模、线程数和文件大小对照,具体说明 gzip 单流与 zstd/lz4 多帧在并行边界上的差异。对做日志/ML 数据管道、性能优化或存储格式选型的读者,可迁移“按新行切帧+多线程解压解析”的方案,同时注意合成数据重复性带来的速度上限与压缩率取舍。

技术文章Daniel Lemire

Transcoding UTF-8 to UTF-16 with replacement at gigabytes per second

文章介绍 simdutf 库新增的 convert_utf8_to_utf16_with_replacement 与 utf16_length_from_utf8_with_replacement 配套接口,用于在 UTF-8 输入含非法序列时仍能转码为 UTF-16,并用 U+FFFD 替换每个错误。其关键思路是先扫描并记录错误偏移和所需 UTF-16 长度,再只对已知合法的区间做转码,因此每个错误固定输出一个替换字符。作者在 1.1 MB 的日文维基文本上测试,单核 Xeon Gold 6548N、GCC 14.3.1 -O3 下,无错误时 simdutf 达 7.0 GB/s,标量实现为 1.7 GB/s,且新流程在有效输入上也可能略快。局限是基准只覆盖无错误的日文文本和特定硬件/编译器,未展示实际非法输入的性能与跨平台表现,代码仍在分支上。

推荐收录,因为文中给出了新接口的具体设计、先扫描记录错误偏移再转码的实现思路,以及 simdutf 7.0 GB/s 对标量 1.7 GB/s 的可核对基准。适合从事 SIMD、字符串编码转换、高性能库或浏览器引擎的读者,其中“先验证再处理”的流程对类似容错转码场景有迁移价值。主要风险是基准仅覆盖无错误的日文文本和特定硬件编译器,实际非法输入与跨平台性能仍需自行验证。

技术文章Daniel Lemire

simdjson 5.0 is out

文章介绍 simdjson 5.0 这一 C++ JSON 解析/生成库的版本更新。核心变化包括 C++26 静态反射正式支持、新增编译期完美哈希的 key selectors 以一次遍历按任意顺序提取字段,以及扩展多种流式解析和切片并行能力。性能方面,数字类 DOM 解析提升 8%–25%,转义 Unicode 文件约提升 80%,序列化因改用 Dragonbox 提升 1.3–1.7 倍。基准仅基于 GCC 16 与单核 Xeon,且文章属发布说明,实现原理和失败边界讨论有限,适合关注 C++ 高性能数据处理与库设计的读者。

推荐收录,因为文章提供了 simdjson 5.0 的具体版本变更、API 示例和可复现的性能对比,尤其是 key selectors 的编译期哈希方案以及 Dragonbox 替换带来的序列化提升,对 C++ 库设计和 JSON 性能优化有直接参考价值。适合使用 C++ 处理大规模 JSON、关注解析/序列化性能的工程师。需注意它本质是发布说明,基准环境单一,不能替代对具体实现和兼容性边界的深入评估。

技术文章Daniel Lemire

How fast can you fix a UTF-16 string in C#?

文章讨论如何在 C# 中高效修复 UTF-16 字符串:当高/低代理项配对错误或落单时,应将孤立代理项替换为 U+FFFD,避免把非法字符串写入磁盘或网络。作者把 JavaScript 中已有的 toWellFormed/isWellFormed 算法引入 C# 库 SimdUnicode,利用 SIMD 指令并行比较多个 16 位码元;合法输入直接返回原实例且不分配,缓冲区版本则逐码元写出。基准显示,在支持 AVX-512 的 Xeon 上,拉丁文本校验达约 69 GB/s,而 IndexOfAnyInRange 仅 33 GB/s;全代理对 Emoji 输入下,SIMD 检查约 53 GB/s,运行时搜索降至 0.4 GB/s,M4 Max 趋势类似。作者还说明结果依赖 .NET 10、Xeon Gold 6548N 与 M4 Max,并引用相关论文与源码,方便读者复现和扩展。

推荐收录:文章给出了 V8 同源的 SIMD 修复算法、C# 实现、无分配边界和 Xeon/M4 实测数据,属于可复现的性能工程证据。适合处理文本解析、Unicode 清洗、网络/存储输入校验的工程师与库作者参考,迁移时需注意 SIMD 指令集、运行时版本和跨平台性能差异。

科研思考Daniel Lemire

A thesis isn’t enough for a PhD

文章讨论在 AI 能生成看似合格学位论文的背景下,博士学位评定不应再以论文文本为核心依据。作者先回顾传统博士流程:修课、资格考试、撰写与答辩论文,并指出答辩常流于形式,论文本身几乎决定是否通过。随后他引用哈佛方面的建议,认为学位论文已不再是评估学生数学素养与独立研究能力的可靠代理,应改为由多位教师进行定期、多面向的线下评估,且必须严格、形成书面记录并可用于未来求职。结论是 AI 使基于文本的评审失效,博士培养与考核制度必须相应调整。不足在于篇幅较短,论证主要依赖引用与个人观察,未给出具体评估设计或实证数据。

推荐收录,因为它给出了明确且可验证的论据:引用哈佛关于“学位论文不再是可靠评估工具”的建议,并指出答辩形式化这一真实失效模式。适合研究生、导师和科研管理者阅读,可迁移价值在于为 AI 时代科研评价制度的调整提供判断依据。主要风险是篇幅短、缺少可落地的评估方案与实证支撑。

技术文章Daniel Lemire

How many strings can you create per second?

文章用微基准测试比较多种编程语言每秒能创建多少条由整数转换而来的短字符串,覆盖 C++ 的 std::to_string、Nim 的 $、Go 的 strconv.Itoa、Node.js/Bun 的 String、Rust 的 to_string 与 itoa,以及 Python 的 str。方法上让循环把结果写入 1024 槽环形缓冲,整数从 0 到 1 亿,每字符串最多 8 位,在 Apple M4 Max 上取五次最佳成绩。结论是 C++ 以 183.8M/s、约 5.4ns 每条大幅领先,Nim、Go、Node.js、Rust 集中在 63-86M/s、12-16ns 区间,Python 最慢,为 22.9M/s、约 44ns。作者解释 C++ 优势来自小字符串优化,短字符串直接存在对象内,无需调用内存分配器;Go 和 JavaScript 等 GC 运行时分配大量短命小对象也相当高效。边界是该结果依赖特定硬件、编译器版本、字符串长度和分配模式,属于微基准,不宜直接外推到所有真实工作负载。

推荐收录,因为它给出了可复现的微基准方法、完整源码和版本信息,并用小字符串优化与 GC 分配差异解释跨语言性能差距。适合关注性能、运行时和语言实现的开发者,可作为评估字符串/对象分配热点的参考。风险是数字依赖 M4 Max 和具体版本,不能直接当作跨平台结论。

工程实践Daniel Lemire

A summer of AI optimization

文章记录作者在2026年夏季前后对六个成熟开源库(roaring、ada、fast_float、simdjson、simdutf、CRoaring)的性能优化。作者通过重放每个提交并在同一台Intel Xeon Gold 6548N上基准测试,以2024年8月为基线量化加速:Go roaring多项操作达2.5–5.9倍,ada吞吐从0.54升至1.28 GB/s,simdutf ASCII校验从83升至160 GB/s,simdjson序列化最高提升2.1倍。多个优化由合作者借助Claude、Cursor、Grok、DeepSeek等工具完成,部分贡献者甚至是AI。作者的核心论点是这些优化技术本身并不新,真正变化在于AI把尝试新想法的成本降到足够低。文章边界也很明确:无法精确归因每个优化中AI的贡献,数据来自单机基准,部分优化未纳入展示,结论更偏工程观察与个人判断。

推荐收录:文章给出六个被广泛使用的开源库的真实性能数据、提交级基准方法和AI工具参与细节,可直接作为性能工程与AI辅助编程的案例参考。对维护基础库、做低层优化或评估AI编码效率的读者有迁移价值;主要局限是单机基准与贡献度不可精确归因,结论应视为方向性证据。

技术文章Daniel Lemire

More than a taken branch per cycle?

文章讨论现代超标量处理器能否在一个周期内执行多个 taken branch。作者用一个包含 if 的 Go 循环做微基准:从字节数组中读取元素,与阈值比较,若大于阈值则写入 last 指针;在始终不命中、但产生两个邻近 taken branch 且不执行存储的场景下测量。结果显示,Apple M4 Max 与 Granite Rapids 平均不到 2 个周期即可完成两个 taken branch,说明某些条件下确实可超过每周期一个 taken branch;AMD Zen 4 表现较差,Zen 5 明显改善。作者附上 benchmark/experiments/ifloop 下的可复现代码,但结论受特定循环、编译器代码生成和微架构影响,不宜直接外推为通用规则。

推荐收录:作者提供了可复现的 Go 微基准、明确的分支场景和多款处理器的对比数据,直接检验了“每周期最多一个 taken branch”这一常见说法。对关注 CPU 微架构、性能优化和底层代码生成的读者有参考价值,可迁移为结合具体处理器与编译器实测、避免把简化模型当硬约束。局限是结论依赖特定循环和硬件,不能无条件外推。

科研思考Daniel Lemire

AI is breaking the academic sorting machine

作者 Daniel Lemire 提出,具备 agentic 能力的 AI 很快能让非顶尖数学家、甚至优秀高中生生成相当于数学博士论文的成果,从而击穿学术界以论文为筛选信号的“人才分类机器”。他认为自 1970 年代同行评审普及以来,研究被封闭成孤岛社群,学术产出的实际功能变成分配教职(博士获得终身轨职位概率约 10% 且持续下降),而非服务真实需求。他援引自己 2024 年发表于 CACM 的文章,主张评价重心应从“发表论文”转向解决问题的实际影响,并预测“论文作为最终产出”的地位会逐步削弱。文章的边界也很明显:以论断和预言为主,缺少数据支撑,也主要针对数学等学科,并未给出替代评估体系的可操作设计。

推荐收录:作者以自身 CACM 2024 文章和同行评审的历史演变为依据,论证 AI 正在瓦解以论文数量与同行评审为核心的人才筛选机制,并主张用问题解决和实际影响替代发表计数。对关心科研评价改革、读研与学术职业路径选择、以及 AI 时代研究方向判断的读者有明确参考价值。主要风险是文章以预言和立场表达为主,缺乏数据与替代方案细节,读者需自行补充证据。

技术文章Daniel Lemire

How did Apple Silicon get 50% faster in three years?

文章以苹果基础款芯片 M2 到 M5(并延伸讨论刚发布的 M6)为例,分析三年间单核性能提升约 52%、多核提升约 83% 的来源。作者借助 Geekbench 6 分数、核心频率、晶体管数量、核心配置、解码宽度和内存带宽等公开数据逐项拆解。结论是苹果与 AMD 不同:约 30% 的 P 核频率提升(3.5→4.6 GHz)解释了单核增长的大部分,而 E 核从 4 增至 6、解码宽度从 8 提升到 10、内存带宽从 100 提升到 154 GB/s 共同支撑了多核与带宽敏感负载。文中还指出苹果 SIMD 仍为四个 128-bit 单元,弱于 Zen 5,但 M4/M5 新增 512-bit SME 矩阵单元。分析基于公开规格与 Geekbench 数据,缺乏自建微基准验证,属于趋势性归因。

推荐收录。文章给出了一套可复用的性能提升归因框架,把代际差异分解为频率、核心数、解码宽度(IPC)、内存带宽与 SIMD 宽度等因素,而非停留在跑分对比,对关注 CPU 微架构演进与性能分析的工程师、研究者有长期参考价值。需注意其数据主要来自 Geekbench 与厂商公开规格,未做自建微基准,结论应视为趋势性解读。

工程实践Daniel Lemire

Faster JSON parsing with SVE2 on ARM processors

文章介绍 Daniel Lemire 团队将 ARM SVE2 的 match 指令用于 simdjson 的 JSON 结构字符分类阶段。NEON 版本通过查表和比较指令在每 16 字节中识别逗号、冒号、括号等结构字符;SVE2 的 match 可用一个谓词寄存器输出匹配掩码,并借 NEON-SVE bridge 与现有 NEON 代码衔接。作者在 Graviton 4/5 上对 22 个标准 JSON 文件做基准,结果显示索引阶段吞吐提升约 3%–9%,整体解析提升约 1%–4%,结构化程度高的文件收益更大,纯数字文件可能略有回退。当前代码需要 SVE2,且默认构建仍走 NEON,尚未做到运行时指令集选择,Apple 处理器和旧 Graviton 也无法使用。

推荐收录:文章不是概念展望,而是基于 simdjson 真实 PR 和 22 个 JSON 语料的可复现基准,给出了 NEON 与 SVE2 match 的指令级实现、收益区间及失效场景。适合高性能解析、ARM SIMD/体系结构和 C++ 库优化读者,可迁移到其他需要字节分类和掩码聚合的场景;但需注意收益有限且依赖 SVE2 与构建配置,不能直接套用到 Apple 或旧 Graviton。

技术文章Daniel Lemire

How did AMD Ryzen get 50% faster in two years?

文章以 AMD Ryzen 7 5800X3D(Zen 3)、7800X3D(Zen 4)、9800X3D(Zen 5)三款同为 8 核且带 3D V-Cache 的桌面处理器为对象,用 Geekbench 6 数据说明两年内单核性能提升约 47%、多核约 58%。作者指出主频仅从 4.5GHz 升到 5.2GHz(约 15%),晶体管则增加约 50%,因此增益主要来自核心变宽:调度宽度 6→8、整数 ALU 4→6、重排序缓冲 256→448、L1 数据缓存 32KB→48KB、每核 L2 由 512KB 翻倍到 1MB,Zen 5 的 SIMD 单元与加载/存储通路也从 256 位全面翻倍到 512 位。结论是“CPU 停滞”并不成立,性能提升源于核心宽度与数据通路扩展而非频率;其边界在于只依赖 Geekbench 一项合成基准,缺少功耗、能效和真实负载验证,Zen 6 桌面核也未展开。

推荐收录,因为文章用可核对的跑分、频率、晶体管数和微架构参数(调度宽度、ROB、缓存容量、SIMD 位宽)把“额外晶体管如何转化为性能”讲清楚,而非停留在简单跑分对比。适合关注 CPU 微架构、性能优化与硬件选型的读者,可作为理解近年 x86 核心变宽与 AVX-512 式扩展趋势的参考;主要风险是数据仅来自单一合成基准,缺少能效与真实工作负载维度。

技术文章Daniel Lemire

How fast is C++23’s std::flat_map?

文章介绍 C++23 新增的 std::flat_map:它用排序的 key 向量与 value 向量实现,查询为二分查找,可借助 std::sorted_unique 直接接管来自磁盘或网络的两个数组,也支持有序插入、批量 insert_range 和批量构建。作者在 GCC 16.1、-O3 -march=native 的 Intel Xeon 单核上,与 std::map 对比随机逐个插入、有序插入、批量构建和随机查找。结论是:约千级规模下 flat_map 可优于或接近 map;但随机逐个插入百万、千万级 key 时性能呈二次增长,极不适用。有序插入、批量构建和随机查找在大规模下明显更快,主要得益于连续内存布局和更低存储开销。适用边界是读多写少、可批量构建或有序写入的场景,不适合频繁随机单点插入。

推荐收录,因为文章给出了具体基准数据、实现机制和与 std::map 的读写复杂度边界,能直接支撑 C++ 容器选型判断。适合关注性能优化、标准库数据结构和系统编程的读者,尤其可迁移到读多写少、批量构建或序列化场景的取舍分析。主要风险是结果依赖编译器版本与硬件,但作者已说明测试环境,结论边界清晰。

技术文章Daniel Lemire

Subnormal floating-point numbers are expensive… on Intel processors

文章用 C++ 微基准测试 IEEE 次正规浮点数在不同处理器上的性能代价,覆盖乘法、数组相加、除法和依赖乘法链,并对比正常、全部次正规及 1% 次正规输入。实验在 GCC 15/clang 17 的 O3 -march=native 下运行,覆盖 Intel Granite Rapids、Emerald Rapids、AMD Zen 5、AWS Graviton 5 和 Apple M4 Max。结果显示 Intel 上次正规乘法约慢 45–50 倍,除法约慢 18 倍,依赖链每步从约 1 ns 增至 30 ns 以上,乘法延迟从 4 周期升至 128 周期;加减法不受影响,正常输入产生次正规输出同样慢。AMD 乘加基本全速,依赖链约慢三分之一,除法约慢一倍;Arm 几乎无惩罚。作者认为最新 AMD/ARM 上可较少担心次正规性能,但 Intel 仍是显著问题;结论来自微基准,实际负载仍需验证。

推荐收录:文章给出跨 Intel、AMD、Arm 五款处理器的可复现微基准与源码,量化了次正规浮点在 Intel 上乘法约慢 45–50 倍、除法约慢 18 倍等关键数据。对做数值计算、HPC、机器学习或游戏引擎的读者,可用于判断何时规避次正规数;但结果属微基准,迁移到真实负载前需结合向量化和数据分布验证。

科研思考Daniel Lemire

The four-colour theorem was only the start

文章从数学家对 OpenAI 的公开信切入,讨论 AI 在数学证明与软件开发中的作用。作者以 1976 年四色定理的计算机证明、自己博士期间使用符号代数软件的经历,以及 Doron Zeilberger 2009 年的预言为线索,说明计算机辅助研究早已引发争议。公开信担心 AI 损害概念理解、署名和学术训练,但作者认为这忽略了学生可能以不同方式研究数学,也低估了加速进展对社会贡献的提升。核心结论是:数学证明和代码编写都将越来越多地借助 AI,坚持纸笔的研究者更像艺术家,其他人需要学会与 AI 协作。文章是观点性评论,未提供实证数据或技术方案。

推荐收录,因为它以四色定理、Zeilberger 预言和数学家公开信为线索,清晰呈现 AI 介入数学证明与代码编写后围绕署名、概念理解和科研训练的冲突。适合关注 AI for Science、科研评价和开发者角色变化的读者,可作为讨论人机协作与学术贡献的参考。主要风险是文章属于短篇观点评论,缺少实证数据和技术细节,不适合当作可复现的方法或工程方案。

技术文章Daniel Lemire

A quick overview of atomics in C

文章以 C11 线程与 stdatomic.h 引入原子变量与内存序。它先解释数据竞争与编译器/硬件重排的原因,再区分 relaxed、acquire 与 release 语义,指出 release 与 acquire 分别配合“我完事”和“确认别人都完事”。通过引用计数写时复制数组的例子,展示 naive 代码会造成泄漏或双释放,并给出用 atomic_fetch_sub 与 acquire fence 的完整实现。最后谈到 threads.h 在不同平台的可用性,以及 x86/ARM 上 acquire-release 的成本差异。目标是让读者理解原子操作与内存序的实用边界。

推荐收录。文章以可运行的示例逐步揭示 C 并发中易被忽视的内存序细节,而不仅是罗列语法;其引用计数释放的完整纠错过程对编写共享资源和锁无关代码很有价值。适合需要深入理解 C 内存模型、或在使用引用计数的系统库中避免数据竞争的读者,也可作为后续探讨 acquire/release 语义的入门材料。

技术文章Daniel Lemire

AI programming: a layered model

作者将当前 AI 辅助编程产生大量代码的现象,与20世纪60-70年代程序员数量激增导致的软件危机进行类比,指出若缺乏纪律约束,AI 生成代码可能让系统质量失控。他提出分层模型:核心层变化缓慢,必须由人阅读代码并强制测试,即使使用 AI 也不允许“vibe coding”;外围层可以快速迭代,允许出现 bug 并由 AI 快速修复。核心层与外围层之间的依赖必须是单向的:外围依赖核心,核心不能依赖外围。文章强调核心区的严格把关与外围区的试错平衡,并指出依赖方向的维持是关键。虽然是一篇方法论随笔而非实证研究,也未涉及工具层面的具体实现,但它为 AI 时代如何组织代码库提供了一种可执行的设计约束。

推荐收录,因为文章针对 AI 辅助编程这一热点提出了有辨识度的分层设计原则,将代码库按变化速度和验证强度分区,并明确了依赖方向,具有直接的可操作性。适合关注 AI 工程实践、软件架构与工程文化的读者,可作为团队制定 AI 编码规范和代码评审策略的参考,其思想也能迁移到非 AI 场景的代码组织与治理中。

技术文章Daniel Lemire

Python sets and dictionaries can have quadratic-time performance

Python的dict和set通常被认为具有平均O(1)的插入与查询性能,本文通过两组实验验证这种看法在理论上和实践中都不严谨。一方面,选择适当间隔的整数作为key可以制造大量哈希冲突,使插入和成员查询的时间随数据规模翻倍而近似翻四倍,呈现二次复杂度。另一方面,即使没有人为构造攻击,当字典规模从1千增长到1百万时,单次查找的时间也因数据超出CPU缓存而大幅上升(实测超过9倍),而使用更紧凑数据布局的fastconstmap库则能保持接近常数的查询时间。作者指出,把哈希表看作常量时间更接近一种简化教学模型而非现实,需警惕该模型带来的认知偏差。文章附带完整代码,适合从事Python性能优化或了解哈希表实际行为的人阅读。

本文由Daniel Lemire撰写,用可复现的代码和实验数据驳斥了“Python dict/set都是O(1)”的常见直觉,并从哈希碰撞和CPU缓存两方面给出成因。内容有原创实验、可量化的结果和替代库,对需要处理大规模键值数据的Python工程师、系统设计者或算法课程教师都有长期参考价值。推荐收录。

技术文章Daniel Lemire

The new Go JSON API: twice as fast, or 1.5x slower?

这篇博客评测了 Go 1.27 新引入的 encoding/json/v2 性能表现。作者与旧版 encoding/json 在三种典型 JSON 文件(推特数据、加拿大坐标数组、目录数据)上做了单核基准测试,并区分了旧 API 使用新后端、旧 API 使用旧后端以及直接用 v2 API 三种配置。结果发现,在把 JSON 解析为 any 的通用路径下,v2 反序列化比原实现快 1.5 到 2.3 倍,序列化快 1.2 到 3 倍;而仅升级到 Go 1.27 不修改代码,旧 API 的序列化在某些场景也能快约一倍。但针对编译期已知结构的 struct 往返测试,旧 API 新后端的 marshal 反而比原实现慢约 1.5 倍,说明 v2 并非所有场景都全面占优。作者还指出新旧 API 在 Unicode 校验、大小写匹配等语义上不同,并非直接替换。文章提供了可复现的基准代码和局限说明。

推荐收录。文章用可复现的基准测试和数据,对比了 Go 1.27 新旧 JSON 实现在不同数据形态和典型路径下的真实表现,并明确指出性能提升并非普适,marshal typed struct 时可能变慢。适合 Go 开发者、标准库使用者和性能调优读者,帮助在新版本升级时做出有依据的取舍,也具有基准方法上的可迁移价值。

技术文章Daniel Lemire

Java’s String.indexOf can be slow (quadratic)

文章指出 Java 的 String.indexOf 在对抗性输入下可能退化为 O(n·m) 的二次复杂度,并以 OpenJDK 25 和 Apple M4 Max 上的实测数据验证。作者将全 a 串作为主串、以 a* 加不同结尾字符作为模式串构造病态用例,测得当模式串长度为 4096 时,对 1MB 主串的一次查找耗时约 1.1 秒。文章随后对比了 Crochemore–Perrin 的 Two-Way 算法,该算法在相同病态输入下始终维持在约 0.3 纳秒/字符,性能差距可达数千倍;但在随机文本上,Java 自带的 indexOf 通常更快,且 Two-Way 有额外预处理开销。因此作者不建议无条件替换,而是强调在可能被恶意控制长模式串的场景中限制长度或改用更稳健算法。

推荐收录,因为它用清晰的可复现实验揭示了标准库中暗藏的最坏情况复杂度,并给出了两种算法在多组输入下的实测对比与明确边界条件。对需要做字符串处理性能优化、实现搜索功能或评估标准库风险的开发者,本文提供了可迁移的测度方法和算法选择依据。

技术文章Daniel Lemire

Parsing IP addresses in C# at crazy speeds

本文介绍在 C# 中利用 AVX-512 指令集实现超高速解析 IPv4 地址的方法。作者使用掩码加载安全读取长度不超过 16 字节的字符串,并处理 UTF-16 编码带来的零字节,再通过点号定位和点积校验快速识别数字。利用 IPv4 地址只有 81 种合法点位置的特点,结合字节重排优化。对非标准地址或未支持 AVX-512 的处理器则回退到 IPAddress.TryParse。实测在 .NET 10 和 Intel Xeon Gold 6548N 上,标准库需要 45.3 纳秒/个,新方法仅 14.1 纳秒/个,约快 3 倍。文章提供完整代码,但只覆盖常见的点分十进制 IPv4,且依赖较新硬件。

直接证据是文中给出了可运行的 AVX-512 C# 代码和详细的基准测试,速度提升约 3 倍,且步骤明确、边界清晰。适合需要处理海量日志、网络包或持续解析 IPv4 的性能敏感型开发者,以及希望学习 .NET 向量化编程的读者。其掩码加载和 UTF-16 处理思路可以迁移到其他短文本解析任务,但代码复杂度较高且受 AVX-512 硬件限制,需要在实际项目中权衡。

技术文章Daniel Lemire

Go 1.27 will make some allocations cheaper

文章以Go语言的内存分配机制为背景,对比栈分配和堆分配的成本差异。堆分配需要回收管理,且Go中返回指针或逃逸变量时也会进入堆分配。Go的堆分配器按尺寸类(8字节、16字节等)取整,并带有额外开销。作者指出Go 1.27以前所有堆分配都走通用函数,1.27开始对小于80字节的小对象使用专用分配路径,以减少函数调用和尺寸类查找。基准测试显示,16字节且含指针的节点分配从9.5ns降至5.5ns,提速约1.8倍。文章同时说明该优化仅对大量小对象分配的程序有效,并非所有负载都能受益。

推荐收录。文章用可复现的基准测试直接量化了Go 1.27小幅优化带来的分配性能提升,并解释了栈/堆分配原理与尺寸类机制,内容深入且边界清晰。适合关注Go性能调优、运行时分配或做性能评测的开发者阅读;其“用小路径替换通用路径”的优化思路也可迁移到其他语言的性能设计。需注意结论限于小对象分配场景。

技术文章Daniel Lemire

Profile-guided optimization in Go

文章介绍了 Go 语言的 Profile-guided optimization (PGO) 原理与使用方法。作者解释了编译器在缺乏运行时信息时依赖启发式做优化决策,而 PGO 通过收集 CPU profile 让编译器了解热路径,从而更激进地内联热函数和去虚拟化接口调用。文中通过三个 JSON 文档的解析基准测试,展示了 PGO 可带来 2–4% 的吞吐量提升,但效果因训练数据与工作负载匹配程度而异,甚至可能出现略微性能回退。作者指出 Go 的 PGO 优化幅度有限但成本近乎为零,适合在发行版构建中默认启用。整体内容提供了可操作的实践指南和定量参考,但仅覆盖单个简单解析场景,未涉及更复杂的工作负载或 profile 采样策略。

本文以清晰的步骤和实际数据展示了 Go PGO 的用法与效果,避免了纯理论描述,为需要优化 Go 程序性能的开发者提供了可直接尝试的方法和预期参考。实验规模虽小,但结论谨慎,强调了 workload 匹配的重要性,可迁移到其他 Go 项目的构建流水线中。适合关注编译器优化、性能工程和 Go 工具链的读者。

技术文章Daniel Lemire

How fast is C++26’s std::hive?

文章对 C++26 标准库新增容器 std::hive 进行了性能基准测试,并与 std::vector 和 std::list 在插入、遍历、删除和内存占用等方面进行对比。实验使用特定编译器、硬件和测试数据,测量了纳秒/元素、指令数和周期数。结果显示 hive 的插入成本约为 vector 的两倍,遍历速度与链表相当且远慢于 vector,主要因跳过字段和缺乏自动向量化;但在元素删除和内存占用上优于 list。作者指出 hive 不是更快的 vector,而是提供了稳定引用和常数时间删除的更好 list。该基准测试为 C++ 开发者在选择容器时提供了具体的性能参考,但结论受限于合成负载和单一硬件平台。

推荐收录,因为文章提供了针对 std::hive 的详细基准测试,用数据揭示了其与 vector 和 list 的性能差距和原因(如指令开销、缓存局部性、自动向量化影响),并给出了实际使用建议。适合 C++ 系统编程和性能优化场景的读者,可帮助他们在需要稳定引用与快速删除时做出容器选择,且评测方法论可迁移至其他数据结构的性能对比。

技术文章Daniel Lemire

Memory-level parallelism: AMD is the king

文章通过 pointer chase 基准测试,系统测量了 Intel、AMD 和 Graviton 处理器的内存级并行度(MLP)演化。核心方法是构建 1 GiB 的随机循环数组,同时运行多条独立的指针追逐路径(lanes),通过观测吞吐量饱和点确定单核可维持的最大并发内存请求数。结果显示,AMD Zen 5(Turin)达到 58 条并发缓存行请求和 24.5 GiB/s/s 随机访问带宽,约为 Intel Granite Rapids 的两倍;Intel 十年间从 10 增长至 30,主要提升在最近两代;Graviton 5 延迟显著改善,但 MLP 停滞在 19。测试在 AWS 云实例上进行,数据与脚本公开。该研究为理解处理器内存子系统的实际能力提供了可重复的实验框架和跨代对比。

推荐收录。文章不是泛泛的性能宣传,而是给出了可复现的指针追逐实验设计、完整的跨平台数据及演化趋势分析,直接揭示了 MLP 这一隐藏关键参数对软件性能的实质影响。对从事性能调优、系统选型或体系结构研究的读者极具参考价值,其测量方法和结论可迁移至各类内存敏感型工作负载的优化中。