Linus 让 Claude 写内核:吞吐量翻 3 倍,还顺手翻出 2013 年的旧账

真正让我停下来多看了几眼的,不是某个新模型刷榜,而是 Linux 内核仓库里冒出来的那个分支名:noref-filemap-read-with-llm。后缀那个 with-llm 明明白白,写代码的队伍里混进了 AI。最离谱的是,开这个分支的人叫 Linus Torvalds,就是那个天天喷烂代码、一句「AI 90% 是营销」挂在嘴边的祖师爷。

他本人在 Patch 说明里大大方方认了:核心代码、测试用例、改动审查到文档草稿,全是手把手带着 Claude Code 搞出来的。跑出来的结果也确实顶,在 8 线程读取同一文件的特定测试里,吞吐量大概是原来的 3 倍。

顺手拆个内核瓶颈

Linus 让 Claude Code 动刀的是 Linux 最核心的内存管理机制。Linux 内核用 page cache 缓存文件数据,日常多并发场景里有个常见操作:多个线程同时小块读取同一个文件。按现有机制,每次读取都得在对应的内存对象 folio 上改原子引用计数,结果就是 CPU 核心之间疯狂执行 lock cmpxchg 和 lock decl,把硬件底层的缓存行颠簸得昏天黑地。

这个顽疾不是新鲜事。早在 2024 年,内核核心开发者 Matthew Wilcox 就提过,它来自真实客户的生产环境。在 Linus 自己的测试机上,8 线程并发小读时,这个瓶颈占到了所有 Load HITMs 开销的 99.92%,基本吃满了 CPU 的总线带宽。补丁说明给出的数据很直观:8 线程吞吐量约为原来的 3 倍,单线程的提升大概一成。

差距为什么这么大,关键藏在「大家都读同一个文件」里。Linux 把文件数据缓存在内存里,后续读取直接从缓存取,省掉重新访问存储设备的开销。但缓存里的内存也会被回收,内核必须保证线程还在读取时这块内存没被抢走。原来的读取路径会给承载缓存数据的 folio 增加引用计数,读完再减回去。几个线程一齐读,大家就反复改同一个计数,处理器核心之间为了保持一致,得来回传递包含这个计数的缓存行。一次读取只有 16 字节,读取本身很快,维护计数的开销反而成了瓶颈——就像八个人都来翻一本书,每次翻页前后都得争着改同一张登记表。

Linus 这组补丁的做法是:缓存中的内存被移除后,延迟一段时间再真正归还给内存分配器,借助 RCU 机制让已经开始的相关读取有机会完成。这样线程能在受保护的读取区间内直接复制数据,减少对共享引用计数的争抢。所以多线程共享同一文件的场景收益才特别明显。

顺着一个 Bug 翻出十年旧账

你以为 Linus 只是让 Claude 写新代码,那就小看了这事的分量。就在那个分支出现的第二天,仓库里又冒出一个 assoc-array-fixes 库,一套按 key 组织、查找对象的数据结构,最初的实现可以追溯到 2013 年。

前几天开发者 Nils Ollrogge 提交了一份 Bug 报告,也带了修复补丁。Linus 看过之后却犯了难:这段代码过于晦涩,逻辑难跟清。于是他借大模型梳理代码,把庞大难读的函数拆开,让不同操作的边界更清楚,再放进用户态测试框架里跑。测试确认了 Nils 报告的问题,还额外找出 3 个 Bug——四个全部可以追溯到 2013 年这个库第一次被合入内核的那次提交。

其中一个例子很具体:某种根节点结构被拆分时,索引用的位段会错位,导致原本存进去的对象再也查不到。补丁说明里有个只需 18 个键就能触发的例子,操作完成后 3 个对象查不到,再次插入相同 key 还会新增对象,没法正确替换原有的。另一个问题藏在内存分配失败的路径里,平时安安静静,一旦某次分配失败,清理逻辑可能顺着指针走进还在用的旧树,触发内核错误检查。测试让每一次内存分配轮流失败,逐个检查异常分支,才把它逼出来。

值钱的早不是手敲代码

Linus 那句「Talk is cheap. Show me the code.」应该没人不知道。这回他给自己的主仓库挂了个带 llm 后缀的分支,等于用行动把话说得更明白了:当代码可以由 AI 来写,真正值钱的是知道该写什么代码,以及判断写出来的代码对不对。补丁说明落到实际用途,得和代码、测试数据对得上;公开到这份上,后续讨论才有抓手。他那句「在我的指导下」,分量就在这里。

那个说「AI 90% 是营销」的人,在自己的内核仓库里真香了。连祖师爷都用 AI 干完整工程活了,手敲代码的那点优越感,确实该收一收了。

相关链接