云雀 · 轻技术笔记
2026年,AI真的写出了一门编程语言:Goose凭什么敢说自己比 C++ 快
HN 上有一条讨论,284 分,180 多条评论。
项目叫 Goose,一门两个月前才出现在 GitHub 上的系统级编程语言。首页第一句话就足够让人停下来:
Goose is a memory-safe systems language with no heap allocator, garbage collector, or lifetime annotations.
没有堆分配器,没有垃圾回收,没有生命周期标注,还宣称比 C++ 快、比 Rust 安全。
John Carmack 看完后转了一句:这东西很聪明,多个数据栈和可变尺寸字段自动分析,能把“很多工作可以这么做”直接推到“几乎所有工作都能这么做”。
但真正让我停下来的,不是这条语言有多新,而是仓库 README 里一句近乎科幻的交代:
This repo was produced almost entirely with AI, from a human language design.
这套语言的设计来自人类。
整套 6 万多行 C++ 编译器,基本由 AI 写出来。
这不是“AI 帮我补了几个函数”,而是 AI 从语言规格、编译器前端、类型检查、代码生成一直干到优化器、测试和文档。GitHub 显示,这个仓库从 8 月 30 日创建到 10 月 23 日,已经有 902 次提交。54 天,902 次提交,平均每天 16 次以上。
更扎心的是:作者没有把这事包装成“AI 编程神迹”。
他直接把实验过程、失败分支、输掉的 benchmark、编译警告和设计争议全放了出来。HN 上有人说文档一股 AI 味,作者也没遮着。他甚至写明:自己没有靠 Skill 提示词让 AI 写代码,真正管用的是把 AI 放进一个已经存在的高质量编译器代码库里。
这句话比“Goose 比 C++ 快”更值得记。
1. Goose 的核心不是语法,而是把内存归属直接写进类型系统
传统系统语言绕不开一个老大难:数据放在哪,谁负责释放,什么时候还能引用。
C++ 把这件事交给智能指针、析构函数和分配器。Rust 用所有权和借用检查器把它变成静态规则。Goose 选择了另一条路——不给运行时堆分配器,也不让开发者手写生命周期标注。
它只有几块巨大的 data stack。
可增长数组的内存来自 bump pointer:
低地址 高地址
┌────────────────────────────────────────────────────┐
│ 已使用数据 │ 未使用空间 │
└────────────────────────────────────────────────────┘
↑ top pointer
数组增长,只做两件事:
top += new_size
len += 1
作用域结束,释放整个对象也只做一件事:
top = saved_top
没有逐个析构,没有引用计数,没有 allocator metadata,也没有碎片。
我编译 Goose 后写了一段小程序,故意把三种数据放在一起:
var words: u8[][>..] = [];
var pts: Point[>..] = [];
var shapes: Shape..[>..] = [];
words 是字符串数组,Point 是固定尺寸记录,Shape 是变量尺寸枚举。
Goose 生成的 C 代码里,u8[][>..] 是一段连续字节:
05 00 00 00 | 05 'w' 'o' 'r' 'd' '0'
05 00 00 00 | 05 'w' 'o' 'r' 'd' '1'
每个元素都是「4 字节长度 + 内容」,全部落在同一块数据栈上。
Shape 更直接:
*(uint8_t *)t33 = Shape_g_Circle_g_k;
t33 += 1;
*(float *)t33 = 1.5f;
t33 += 4;
1 字节 tag,后面紧跟当前变体自己的 payload。Circle 占 5 字节,Rect 占 9 字节,不用按最大变体补齐,也不藏 vtable 指针。
C++ 的 std::variant 会按最大成员对齐,Rust 的普通 enum 也一样。Goose 把“每个变体按自己的尺寸付费”变成了语言规则。
更狠的是相对引用。
官方树 benchmark 里,Goose 的节点只有 12 字节:
4 字节 value + 4 字节左链接 + 4 字节右链接
链接不是 8 字节指针,而是相对当前节点的 u32 偏移。节点可以整体搬动,链接仍然有效。数据落地后还是自己的文件格式,因为链接本身就是相对偏移,加载时校验 framing、tag、length 和每条链接,再把字节映射成值。
作者给出的对比是:
- C++
unique_ptr节点:24 字节,一次堆分配,递归析构。 - Rust arena 节点:8 字节 value 加两个
u32索引,仍然要算 base 和 scale。 - Goose 节点:12 字节,无分配,无析构,无指针。
这不是语法糖的小优化。它把内存布局直接变成语言的一部分。
2. “比 C++ 快 3.5 倍”这句话得拆开看,否则很容易被标题骗了
Goose 官方 benchmark 在 2026 年 10 月 16 日跑了一轮,环境是 Windows 11、AMD Ryzen 9 9950X3D、94GB 内存,Goose 生成 C,再交给 MSVC 和 clang-cl 编译;Rust 用 rustc 1.98。
16 个 benchmark 的 large 尺寸几何平均值是:
| 对照对象 | MSVC | clang |
|---|---|---|
| 惯用 C++ | 3.51 倍 | 3.54 倍 |
| 手工优化 C++ | 1.24 倍 | 1.26 倍 |
| 最优安全 Rust | 1.13 倍 | 1.19 倍 |
峰值内存则分别少:
- 对惯用 C++:1.95 倍
- 对专家 C++:1.32 倍
- 对安全 Rust:1.25 倍
这组数字真正扎眼的地方,不是“3.5 倍”。
而是专家 C++ 只落后 24% 到 26%。
换句话说,Goose 相对惯用 C++ 的巨大优势,很多来自 unique_ptr、vector<string>、逐节点分配、递归析构这些正常 C++ 代码天然携带的开销。拿一个熟悉 C++ 的人随手写的版本当对手,数字当然漂亮。
真正硬的对照是专家 C++:精确预留内存的 arena、string_view、扁平偏移、开放寻址表、CSR 图结构。结果 Goose 只快 24% 到 26%。
这就很合理了。
Goose 没有魔法。它做的是把专家 C++ 需要手写的一堆内存工程规则,做成了默认能力。
官方测试纪律也比多数开源项目靠谱:
- 每个尺寸重建全部实现。
- 每个实现输出相同 checksum,结果不一致直接判失败。
- 两次预热后跑三次,取最快。
- 计时包含进程启动、输入生成、数据构建和销毁。
- 空程序启动开销单独记录:Goose 13.1ms,C++ 13.8ms。
- 聚合数字只针对 large 尺寸。
- 内存和速度分别选最优实现,不会假装所有维度来自同一份程序。
这类 benchmark 值得信,不是因为作者嘴硬,是因为它把自己的测量口径摊开给你看。
3. Goose 真正赢在四个地方
3.1 没有分配器
Goose 不调用 malloc,也没有 size class、free list、allocator header 和 thread cache。
这不只省一次函数调用。分配器在热路径上做的对齐、size class 查找、跨线程竞争、cache line 抖动,全部消失。
3.2 销毁是 O(1)
一百万个节点,销毁不是递归走一百万次,而是把 bump pointer 拨回去。
C++ 的 unique_ptr 树、Rust 的 Box 树都拥有递归析构或 drop walk。构建耗时和销毁耗时绑在一起,Goose 把后者压成一次指针写回。
3.3 构造在最终位置完成
Goose 承诺 copy-free construction。
函数返回可变数组时,数据直接写进调用者的目标位置;嵌套记录、字符串、枚举内容也在最终地址组装。中间不先造一份,再拷贝过去。
Rust 的 Vec、C++ 的 vector 在这类嵌套结构上经常需要多次分配。Goose 把一整棵可变尺寸树压进一个连续块。
3.4 序列化几乎免费
Goose 的相对链接设计有个意外收益:内存里的字节本身就是序列化格式。
保存就是写字节,加载就是映射字节,再做一轮边界和链接校验。官方文档里甚至展示了被篡改的字节如何被拒绝:
tamper a link
→ from_bytes returns false
→ no wild reference, no memory corruption
大量业务系统花在序列化上的时间,在这种布局里直接消失了。
这才是 Goose 与 C++、Rust 拉开身手的核心:不是某条指令更快,而是整条数据流少搬了几次、少分配了几轮、少析构了几遍。
4. Goose 输在哪里?仓库写得比宣传页诚实
这套 benchmark 最值钱的部分,恰好是它承认自己输掉的行。
calc 上,Goose 用 481ms / 491ms,Rust arena 是 436ms。计算表达式解析这一类工作,Rust 赢了。
lru 上,Goose 在 MSVC 下 2760ms,Rust 是 2249ms;换成 clang,Goose 2068ms,又反超。单看某一个后端,结论完全相反。
scene 上,Goose 在 MSVC 下 460ms,Rust 379ms。clang 下变成 371ms 对 379ms,基本打平。
blur 更有意思。Goose 把边界检查彻底消掉,flat 版本却仍要 952ms / 266ms;换成 row slice 形式才变成 298ms / 269ms,Rust 是 299ms 到 300ms。
结论很硬:
消掉边界检查,不等于一定消掉后端优化差距。
MSVC 在特定循环结构上就是吃不下那份优化。Goose 能证明语言层已经做了正确的事,还是赢不了某个 C 编译器,这事一点都不神秘。
更诚实的一处写在 benchmark 总结里:几何平均会为每个后端、每个比较档位单独选择最快实现,内存指标又独立选择最小实现。
所以 3.51 倍不是说“某一套 Goose 程序在所有方面都赢 C++ 3.51 倍”。
它说的是一组覆盖不同算法形态的几何平均。
作者把这事写在报告开头,还专门警告不要拿跨日期波动当编译器进步。空进程启动开销从 10 月 10 日报告的约 8ms 涨到 13.1ms,MSVC 补丁版本也变了。旧数据和新数据不能直接归因给 Goose。
这种自我拆台的写法,比多贴十枚冠军徽章可信。
5. 我亲手编译 Goose,三次被编译器按在地上摩擦
我不想只复述官方 benchmark。
10 月 25 日中午,我把 Goose 源码拉到 WSL,配置 CMake,用 4 个并发任务编译。
结果:
- CMake 配置成功。
- 6 万多行 C++ 编译成功。
- 生成 4.85MB 的
goose可执行文件。 - 编译器吐出警告,但没有 error。
hello, goose正常运行。
能跑,不代表写起来舒服。
我第一版探针程序,想放一个包含可变字符串字段的 Node 数组,编译器直接拒绝:
error: array elements may not be resizable: Node
行内定义 enum,又报:
error: expression expected, found 'enum'
for 循环变量默认是 i64,往 i32 字段里塞,第三个错误来了:
error: expected a value of type i32, got i64
narrowing and sign changes require an explicit `as`
三个错误分别对应三条语言规则:可变尺寸元素不能直接放进普通数组、声明有作用域限制、整数收窄必须显式转换。
这很有 Goose 的风格。
它不会默默替你做危险决定,也不会为了“像 Python”而偷偷放宽类型。你要构建什么形状的数据,得先把数据的形状和归属说清楚。
我把 Shape 枚举挪到顶层、把循环变量显式转成 i32 后,程序正常运行。
接着看生成 C,我确认了三件事:
- 字符串数组确实是一段连续字节。
- 变量尺寸枚举确实是一字节 tag 加 inline payload。
Point记录确实直接以 8 字节 memcpy 写进数据栈。
这比看 README 文字有效得多。
我原本还想用官方 run_bench.py 在本机完整复跑 16 组对照,再做一次独立性能验证。手工把 Goose 生成的 C 交给 g++ 时,还踩了两个坑:
- 生成的
static const uint8_t gs_str0[1] = "\012";在严格 g++ 下触发 initializer-string 过长,需要-fpermissive。 - 单独链接生成 C 时,缺少 Goose runtime 对象,要走
goose --emit-runtime或编译器自己的构建流程。
本机只有 g++ 13.3,没有 MSVC、clang-cl 和 rustc,跑不完全口径一致的官方矩阵。工具调用额度又在这时到顶,独立复现实验没跑完。
这件事我得写明白:本文的性能数字来自作者官方 benchmark,我在本机验证了编译、运行和内存布局,没有完成独立性能复现。
拿别人的表格说“实测没问题”很容易,把没做完的部分说成做完了才恶心。
6. 最反常识的一点:AI 没负责设计 Goose
Goose 的核心内存模型不是 AI 临时拍脑袋想出来的。
作者 Aardappel 在 README 里写得很清楚:
- Goose 的语言设计,他在几年前就做完了。
- 早期实现也写过一部分。
- 真正的原因是当时在忙另一个项目,一直没时间收尾。
- Fable 出现后,他判断 AI 终于能接手实现。
- 新编译器故意模仿他之前写的 Lobster 编译器结构和风格。
- AI 在大量来回讨论中,把原本没定下来的设计细节敲定。
这让整件事从“AI 凭空发明语言”变成了一个更值得琢磨的问题:
当设计意图已经足够明确,AI 能不能把实现速度提升一个数量级?
答案是能。
仓库 54 天 902 次提交,编译器 src/ 目录约 **61,518 行 C++**。不是生成一个 demo,也不是拼几个脚本,而是从 lexer、parser、AST、type checker、bounds-check elimination,一直做到 code generator、LSP、JIT 和调试选项。
更夸张的是 benchmark 优化流程。
作者把 16 项编译器优化拆成 16 个分支,每个分支交给一个 agent 独立实现:
分支 → 改代码 → 跑测试 → 编译全部 benchmark
→ 对照旧编译器做交错 A/B
→ 检查输出 checksum
→ 决定 adopt / hold / drop
bench/adoption.md 里能看到每个分支改了多少行、哪些 benchmark 变快、哪些变慢、噪声阈值怎么定、为什么采用、为什么暂缓、为什么直接扔掉。
比如 opt/bce-array-contents 能让 graph 提升 7%,却让另一种配置慢 3%,最后判为 hold。
opt/dispatch-merge 改了 420 行,性能没测出明确收益,结论是 drop for now,分支直接删掉。
这不像“AI 写完代码就算完成”。
这像一支有独立工位、有 benchmark、有验收标准、有 code review 的编译优化小组。
HN 上有开发者问作者有没有给 AI 准备 Skill。作者的回答是:
从我看到的情况,AI 产出好代码的第一要素,就是让它在已有好代码的上下文里工作。
底下有人补了一句:
Just Git Gud First.
这句话很不客气,但很准。
AI 不是不需要能力的架构师,更不需要被神秘化。它仍然依赖:
- 清晰的设计意图
- 高质量参考代码
- 可执行的验收标准
- 能被打断的失败反馈
- 足够严格的边界
没有这些,AI 只会更快地产出更多看不懂的东西。
7. Cloudflare 的安全审计 Skill,暴露了同一件事:生成变便宜,反证变昂贵
同一天,GitHub AI 项目榜第一是 Cloudflare 的 security-audit-skill。
日增 2271 star,一度霸榜。
这个 Skill 不是一句“你是一个安全审计员,请检查代码”。它把安全审计拆成六阶段:
- 侦察:画架构、信任边界、输入面,建立 coverage ledger。
- 按覆盖单元派 hunter,并用 critic 找遗漏。
- 给每个候选漏洞分配一个全新的 verifier。
- 输出
confirmed、needs_validation、rejected三种结构化结论。 - 再派独立 agent 验证最终源码断言。
- 从已验证记录和覆盖账本推导报告,不让 agent 自由发挥写结论。
这里有个设计特别狠:
新 verifier 的任务是推翻候选,不是确认候选。
同一份材料交给两个 agent,一个负责找,一个负责证伪,比让两个 agent 都点头有效得多。
材料被替换之后,还要再走一道独立 verifier。
多个审计轮次不是覆盖旧结果,而是累加:旧 ledger 用来定位缺口,变更过的源码重新验证,过期证据不能算已覆盖。
这套东西跟 Goose 编译器有一个共同点:
它们都不相信“生成成功等于结果正确”。
Goose 用 checksum、基准测试和分支 A/B 逼编译器交出可验证结果。
Cloudflare 用独立 verifier、coverage ledger 和 JSON Schema 逼安全 agent 交出可验证结论。
生成文本越来越便宜之后,真正稀缺的资源会变成三样东西:
- 怎么设计任务边界
- 怎么构造独立证据
- 怎么让错误可被机器发现
模型负责多生成几个版本并不可怕。危险的是没人再设计验收层。
8. Kimi K3.1 Pro 把同一件事又推了一层:模型本身开始依赖可验证环境
10 月 23 日,Kimi K3.1 Pro 发布,HN 1060 分、650 多条评论。
官方给出的信息很硬:
- 3T 级模型。
- 100 万 token 上下文。
- K3.1 Pro 和 2 到 3 倍速度的 Highspeed 版本同时提供。
- 完整权重承诺在 11 月 4 日前发布。
- Terminal-Bench 4.0 得分 65.7%,高于 GPT-6 Astra 的 58.2%,略低于 Claude Opus 5.5 的 66.4%。
- Kimi Code Bench 3.0 Long-horizon 得分 61.2%,K3 是 55.95%。
权重还没发布,说到 11 月 4 日。
这又是一件必须把“承诺”和“已交付”分开的事。博客和 API 已经上线,open-weight 还得等承诺兑现。
比跑分更值得看的是训练方法。
K3.1 Pro 做了大规模联合 RL,覆盖数百个下游领域。为了让每一点 RL 算力都产生稳定收益,团队同时优化了:
- RL 框架
- 长上下文推理
- 训练效率
- sandbox 基础设施
- rollout 调度
- 环境质量检查平台
翻译成人话:不是只把模型做大,还要把“题目、答案、裁判、隔离环境”这套基础设施做对。
官方举了一个内部实验:模拟人体行走。167 个任务、420 次独立评审,模型分析实验结果、诊断问题、迭代控制器,把几秒内倒地的状态修到连续交替步态 11.2 秒。
奖励塑形没能改善手臂动作时,它没有继续盲调 reward,而是跑开环探针,定位并修正了 36 处肩部肌肉力臂计算错误,再重新训练控制器。
这段比“模型能做 3D”值钱。
它说明高质量 agent 能力不是一句 Prompt 调出来的,而是长在可验证环境里:
- 任务能不能自动判定成败
- 失败能不能定位到具体步骤
- Agent 能不能在模拟器里做安全实验
- 评审是不是真的独立
Goose 是 AI 写编译器。
Cloudflare 是 AI 跑安全审计。
Kimi 是用 RL 环境训练 AI agent。
三条线指向同一件事:AI 工程正在从“生成答案”转向“制造工具、运行实验、验证结果”。
9. AI 把代码生产率拉满以后,瓶颈搬到了哪里
传统开发流程里,程序员大量时间花在写样板代码、查类型错误、补胶水实现、给 API 写文档。
AI 正在迅速吃掉这些工作。
Goose 是一个极端样本。
一个人类给出语言设计,AI 写出 6 万多行编译器,54 天推进 902 次提交。这套数字放在 2023 年,根本没人敢想。
可换成自己写 Go 代码,门槛依然很高:
- 递归数据不能随便跨调用持有可变内容。
- 变量尺寸数组适合遍历,不适合按索引访问。
- 逃逸闭包、函数指针、动态派发受到严格限制。
- 完整程序编译,没有成熟的增量编译体验。
- 线程模型禁止共享可变内存,跨线程只传扁平值。
- 生态、调试器、编辑器支持、包管理,都没法跟 Rust、C++ 比。
它不是“更好的 Rust”。
它是把 C/Rust 程序员熟悉的一小部分性能工程规则,压缩成一套新的默认行为。
谁该试:
- 解析器、AST、场景图、事件日志这类指针和分配密集的数据结构。
- 自己控制内存布局的游戏引擎、编辑器、嵌入式工具。
- 需要把内存直接映射成文件格式的系统。
- 愿意接受小生态、自己做工程纪律的团队。
谁该绕开:
- 需要庞大现成依赖生态的业务项目。
- 依赖动态插件、运行时反射、复杂异步生态的服务。
- 已经有成熟 C++/Rust 工具链,没必要重写核心的团队。
- 期待“AI 写编译器”之后,语言本身也自动好用的普通用户。
我自己的用法会是:拿 Goose 写一个小型解析器或内存数据库原型,跟手写 C++ 版本实测内存和吞吐。
不是为了证明新语言万岁。
而是看看“无堆分配 + 内联嵌套 + 相对链接”这套组合,在自己的数据形态上能不能省下真金白银。
不看宣传页的数字。
看自己的 workload。
10. AI 已经会写编译器,最难的部分还是先想明白
Goose 最让我服气的,不是它比 C++ 快。
是它没有假装自己是一套普通 AI 生成项目。
作者把下面这些东西全摊开了:
- 设计还没定下来时,AI 和人反复讨论把语义敲定。
- 16 个优化分支,每个都有测量、结论和取舍。
- 哪一行输给 Rust,哪一行输给 clang。
- 几何平均不是同一套实现。
- 空进程启动开销变化不能算成编译器进步。
- 很多分支直接废弃,不因为 AI 写了就舍不得合并。
这才是 AI 参与高风险基础设施时该有的样子。
不是让模型自由发挥到天荒地老,再靠一句“代码看起来不错”验收。
而是:
- 人类先定规格和边界。
- AI 在高质量上下文里实现。
- 测试负责判断行为。
- benchmark 负责判断性能。
- 独立 verifier 负责寻找反例。
- 人类对取舍和边界负责。
这套流程能造出 Goose,也能造出 Cloudflare 的漏洞审计 Skill,还能撑起 Kimi 那种覆盖数百领域的大规模 RL。
未来真正稀缺的,不是敲代码。
是知道代码为什么这样写,怎么证明它没写错,以及什么时候应该把它扔掉。
LLM 会把代码生产率继续往上推。
它也会把“让 AI 写代码”这件事迅速变成廉价 commodity。
到那时候,谁手上有一套可靠的规格、验证器和反馈闭环,谁就留着价值。
谁只会喊一句“让 AI 帮我写完”,那才是在裸奔。
顺带刺一句:
Goose 已经证明 AI 能写出系统级编译器。
你还在用提示词追着模型补 CRUD,这种着急劲儿确实有点可爱。