Live Nov 18 · Cohort 3Nov 18, 19:00 MSK — free hands-on AI agents live workshop · Live Cohort 3 starts Nov 23Join Nov 18 Live →Cohort 3 (Nov 23)
ReleaseResearch Paper · For R&DHabr AI→ original

Goose language "faster than Rust": how the benchmark evened out once the data layout was fair

Goose, a language written by an AI, showed a 1.9x speed advantage and a 1.8x memory advantage over Rust. The blogger MrTeamlead noticed that the Rust version stores strings on the heap, while Goose keeps them inside the struct. Once the layouts matched, the result was 46.7 vs 46.5 ms. After the criticism, Goose's author removed the disputed benchmark from the repository.

AI-processed from Habr AI; edited by Hamidun News
Goose language "faster than Rust": how the benchmark evened out once the data layout was fair
Source: Habr AI. Collage: Hamidun News.
Listen to article
Article Fact Sheet & Key Figures
ParameterDetails
Primary sourceHabr AI ↗
Editor-in-Chief
Key metric #1Compare identical data layouts, not whole languages
Goose really does save memory29 bytes per order vs 153–233 in Rust
Key metric #3Goose has no parallel loops or SIMD yet, so its advantage is partial

Goose is doomed to start a holy war: an AI wrote a programming language that supposedly beats C++ and Rust. We'll leave the flame war to the fans. The artifacts left over from the argument are far more interesting: they show how such comparisons work and where the catch hides.

What MrTeamlead found

In two videos, the blogger MrTeamlead dissects the records_fixed.goose benchmark. According to its authors, Goose beats the Rust version by 1.8x on memory and 1.9x on speed. The blogger shows that the Rust code can be made 6.7x faster if you add parallelization.

The analysis by the author of the Habr article shows that there are two key changes:

  • Vec::new() was replaced with Vec::with_capacity(N). This change is debatable: the benchmark models an event stream, and the number of events is not known in advance.
  • String was replaced with MyString, which stores up to 15 characters directly inside the event. This change is fair.

In the Goose version, the text lives inside the record, while in the Rust version it sits on the heap via String. The data layouts differ, so the comparison is unfair. When the text was placed in Rust the same way, the result was 46.7 vs 46.5 ms. In effect, the blogger wrote the missing records_fixed.rs.

Goose has another benchmark, records_var.goose, where word length (4–15 letters) is a parameter of the data generation rather than a size known to the code. For that one, records.rs remains a valid counterpart. Goose's author answered the criticism by saying that records_fixed was only an illustration and the real benchmark is records_var. He removed the disputed file from the repository.

How Goose handles memory

The main idea is data stacks. These are not call stacks: they contain no function frames, only data. They are freed like a stack: when execution leaves a scope, the top moves back. Memory is reserved up front but committed to the process lazily.

The compiler calculates the number of data stacks at compile time from the deepest call chain. Only functions that hold growing arrays count, and what matters is the maximum number of such arrays alive at the same time. No new stacks appear at runtime, and a function that has finished hands its stack to subsequent calls. The price of this approach is a restriction on recursion. At the moment of a recursive call, the function must have no live growing arrays. Anything that has to outlive the call is created outside and passed by reference.

An example with an order containing two items (id, customer name, list of products) makes the difference obvious right away:

  • Goose: 29 bytes per order and zero heap allocations.
  • Rust: 233 bytes when built via collect and 153 after shrink_to_fit(), plus four heap allocations.

You can do the same thing in C, since Goose is a transpiler. But by hand it is brittle: fine to look at, dangerous to change.

What this means in practice

The first takeaway concerns the honesty of measurements. Before comparing "language A is faster than language B," check whether the data sits in the same layout. Often the winner is not the language but how the data is placed in memory. The second takeaway is about vibe coding. If an AI writes the code and there is almost no time for review, a language with predictable memory, without heaps and allocators, lowers the risk of ending up with a slow solution by default. For such scenarios, Goose looks more convincing than Rust, where "naive" code easily turns out to be inefficient.

The limitations matter too. Goose wins where there are many memory allocations and the computation runs in a single thread. To catch up in pure computation, it needs parallel loops (par for) and vectorization (simd for), and those have yet to be implemented. For scale: the repository is less than three months old (August 2026), while Rust took five and a half years to get to rayon. The language's fundamental problems have not gone away.

The main lesson is broader than one project. Orca, which the article's author discusses at the end, started in March 2026 and has collected almost 17 thousand commits and more than six million lines of code, including tests. Previously, such a language would have remained a pet project for years. Now the speed of building tools with AI is such that "black goose-swans" have become reality. Benchmarks, meanwhile, need to be re-checked immediately.

Story

Key Questions Answered

What MrTeamlead found?

In two videos, the blogger MrTeamlead dissects the records_fixed.goose benchmark. According to its authors, Goose beats the Rust version by 1.8x on memory and 1.9x on speed. The blogger shows that the Rust code can be made 6.7x faster if you add parallelization. The analysis by the author of the Habr article shows that there are two key changes: Vec::new() was replaced with Vec::with_capacity(N). This change is debatable: the benchmark models an event stream, and the number of events is not known in advance.

How Goose handles memory?

The main idea is data stacks. These are not call stacks: they contain no function frames, only data. They are freed like a stack: when execution leaves a scope, the top moves back. Memory is reserved up front but committed to the process lazily. The compiler calculates the number of data stacks at compile time from the deepest call chain. Only functions that hold growing arrays count, and what matters is the maximum number of such arrays alive at the same time.

What this means in practice?

The first takeaway concerns the honesty of measurements. Before comparing "language A is faster than language B," check whether the data sits in the same layout. Often the winner is not the language but how the data is placed in memory. The second takeaway is about vibe coding. If an AI writes the code and there is almost no time for review, a language with predictable memory, without heaps and allocators, lowers the risk of ending up with a slow solution by default.

ZK
Zhemal Khamidun — CPO at Alpina Digital, product manager of AlpinaGPT. Building AI products since 2019. Hamidun News is a pet project that grew into a production aggregator with 6,000+ readers.
✦ Unified AI Workspace · Nomad

Test Frontier LLMs & Autonomous Agents in One Workspace

Run Claude Opus 5.5, GPT-6, Gemini 3.1, and DeepSeek side-by-side in Nomad AI (nomadnet.ai) — unified model routing, deep research, and multimodal workflows under one subscription.

Try Nomad AI →Launch Nomad Agent
What do you think?
Loading comments…