返回

文章详情

鹅编程语言

Hacker News2026年10月24日 19:27

一种内存安全的系统语言,没有堆分配器、垃圾收集器或生命周期注释。在这个代码库的基准测试中,Goose 运行速度快于 C++ 和 Rust,同时使用更少的内存。教程 · 参考 · 规范 · 包 · 示例 · 基准测试 · 标准库 Goose 的语法让 C 和 Rust 程序员感到熟悉,但没有堆。每个动态值在由编译器管理的数据栈上内联存在。增长会推进一个指针,当其作用域结束时,内存就会被释放。语言的类型和生命周期规则使得这个内存模型安全可用。为什么 Goose 比 C++ 和安全的 Rust 更快,同时又是内存安全的。在超过十六个基准测试中,Goose 在典型的 C++ 速度上运行 3.3 倍,手动优化的 C++ 速度上 1.16 倍,最佳安全 Rust 速度上 1.12 倍,同时使用的内存分别少 1.9 倍、1.3 倍和 1.2 倍(结果)。这些增益来自于 Goose 的数据布局和内存模型。没有分配器,没有垃圾回收,没有引用计数,没有析构函数。内存是一组由编译器静态分配的数据栈。释放一个包含一百万个元素的结构只需一次存储,无论其嵌套多深。增长保留引用。指向增长数组的引用在数组存在期间始终有效。你可以保持类型化引用,而 C++ 必须保留,安全 Rust 在相应基准测试中使用 u32 索引。内存安全没有注释。没有生命周期语法,没有别名或排他规则,没有不安全。编译器推断每个引用所根植的内容,并拒绝可能超出其所有者生命周期的引用。嵌套数据保持内联。一个字符串、一个字符串数组、一个具有可变大小字段的记录以及一个包含这些记录的数组都是一组连续的块,而内部没有指针。一个 160 字节的记录在 C++ 中分配 29 字节,而在 Goose 中没有。枚举的成本只取决于它们所持有的内容。可变模式的代数数据类型 (ADTs) 为每个值提供其自身变体的大小,而不是最大的:在行使其的基准测试中,内存少 4 倍,速度是 Rust 枚举的 2 倍。链接比指针更窄。相对引用以 1、2 或 4 字节的偏移量存储一个类型化、已检查的链接。由它们构建的结构是位置无关的,因此你的数据结构已经是其文件格式:保存是一个写入,加载是一个读取加上一个拒绝恶意字节的验证过程。一切都是在原地构建的,保证做到。一个值通过任何深度的调用被构造到其最终目的地。items.push(parse(line)) 将解析的记录直接写入数组,返回一个可增长的数组没有成本。跨多个调用的返回。return err from load 从上面的任意数量框架中返回,静态检查,没有展开器,没有 Result 类型,任何调用上都没有 ?。线程之间没有共享。一个工作程序被编译为一个独立的程序,具有自己的内存,平坦的值通过类型队列交叉作为 memcpy。数据竞争、锁、原子和内存排序在语言中不存在。没有开销的泛型和高阶函数。一个无类型参数是泛型。函数值是在编译时的实体,因此 xs.filter() { it > 0 } 编译成其看起来像的循环,并将其结果直接构建到其目的地。原始 C 输入,原始 C 输出。Goose 编译为一个 C 文件,因此它可以在任何 C 编译器中运行,并通过 extern fn 直接调用 C。捆绑的 TinyCC 后端在进程中编译并运行程序,没有构建步骤。教程通过示例逐步讲解这一切,参考文献按主题覆盖整个语言,规范提供了确切的规则,基准测试中包含了数字和损失。特性 本节集中介绍 Goose 的独特之处。教程更详细地解释了这些特性,而示例显示了 31 个完整程序中的这些特性。一个内存模型:栈,作用域退出是释放 一个程序拥有本地调用栈、静态数据和 N 个数据栈,编译器计算出 N。数据栈是一个大型地址空间保留,有一个增长指针,且没有其他内存。每个栈最多只能有一个可调整大小的值,它始终位于顶部,因此增长从不移动任何内容,也不检查容量。所有这些都是在编译时证明的;运行时只跟踪增长指针。for round in 3 { var scratch : u8 [ >.. ] = [] ; // 仅增长:增长是指针增加 for i in 100000 { scratch . push ((i % 256 ) as ! u8 ) ; } print ( "round " , round , ": " , scratch . len , " bytes" ) ; } // 释放:一次存储到栈顶 没有什么移动,因此引用在增长中依旧有效 struct Item { id : i32 , weight : f32 } var items : Item [ >.. ] = [] ; let first .= items . push ( Item { 1 , 0.5 }) ; // 对元素 0 的引用 for i : i32 in 2 .. 1000001 { items . push ( Item { i , 0.0 }) ; } first . weight = 99.5 ; // 仍然有效,一百万次推送后 push 返回对新元素的引用,因此程序可以在构建数组时链接元素。一个 vector<T> 或 Vec<T> 可能会重新分配,无法提供这个保证。

阅读全文 →

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

☕请我喝杯咖啡