Skip to content
← Blog
benchmarksRustElixirAI coding agents

398 commits vs 2: how to run a fair language benchmark with AI-written code

Brice Ayres /

Short answer

Before DHH posted his Campfire benchmark, GitHub shows the Rust port had about 400 commits from three authors, while the Go and Elixir ports had two commits each. Measured from the first port, Rust ran 4.4 times faster than Rails and Elixir 3.3 times, and once community PRs applied similar optimizations, Elixir matched or beat tuned Rust on some read routes. A fair benchmark gives every option the same prompt, the same effort budget and the same freedom to change the design.

Two runners at the starting line of an empty high school track in Texas at night

Two days ago we wrote about DHH’s Campfire shootout: AI agents ported 37signals’ Campfire from Rails to Rust, Go and Elixir, and Rust came out fastest. His argument was that if agents write the code and nobody reads every line, the fastest language agents can write well wins.

Since then, people have dug into the repos. What they found is a good lesson in how to benchmark anything, and especially code written by agents.

What the commit history shows

The three ports are public on GitHub. We counted commits on each one up to the moment DHH posted his comparison on October 4:

PortCommits before the benchmark postAuthors
Rust4003
Go21
Elixir21

The Rust repo was created on September 26, so those 400 commits came over about a week. The Elixir port’s first commit is titled “Port Campfire to Elixir with Rails parity and Rust benchmarks,” and it landed the morning of the same day the results were posted.

Others found the same gap. Developer @jskalc summarized it: “Rust’s first port from Ruby: 4.4× Rails. Elixir’s: 3.3×. Then Rust got 398 commits and 18 perf PRs. Go was ported from that tuned Rust. Elixir got one small tuning pass.” (post)

José Valim, Elixir’s creator, looked at the Rust repo’s own early numbers and found that they “are in same order of magnitude as Elixir/Go (sometimes worse)” (post).

So the first-pass ports were close. The big gap came later, after a week of tuning that only one port got.

What happened when Elixir got the same treatment

DHH invited patches, and people sent them. Two pull requests are worth reading.

Zach Daniel’s PR went after the design. Among other changes, it “Replaced the single database process with a pool of read-only connections plus one writer,” moved message caching from Redis into ETS, and fixed a bug where Bandit closed WebSockets that hadn’t sent anything for 60 seconds. Action Cable clients mostly listen, so idle chat tabs kept getting disconnected.

A second PR from GitHub user lau built on that and posted these numbers against the tuned Rust port, in requests per second:

RouteElixir (improved)Rust (improved)
Room page17,23726,796
Messages page25,23828,335
Sidebar32,12127,538
Search26,79025,488
Post a message1,9956,101

Rust still wins on writes and on the room page. But on two of the five routes, Elixir is ahead. That’s very different from the original chart.

@jskalc also noted a limit of the benchmark itself: it has no writes on the read routes, and he believes both tuned versions are hitting cache nearly every time, “so it’s not very realistic” (post).

In fairness to DHH

It’s worth being fair here. DHH has said he has no stake in the outcome: “I don’t have a horse in this race. If you can get the elixir to go faster, awesome! Send a patch and I’ll merge it” (post). He’s also said he didn’t spend time on the other ports because he isn’t interested in those stacks: “I kicked off six conversions of an open source app to see where the agents would take them” (post).

And Brian Cardarella, who runs the Elixir consultancy DockYard, pointed out that the benchmark “showed how much faster Elixir is than Ruby” (post).

The point isn’t that anyone cheated. It’s that the result reflects effort as much as language.

How to run a fair benchmark

Whether you’re choosing a language, a framework or a vendor, the same rules apply.

Give every option the same budget

Same prompt, same number of tuning rounds, same hours. If one option gets a week and another gets an afternoon, you’re measuring the week.

Give every option the same freedom

The Elixir port was told to keep Rails parity, including Redis and the Rails-style design. The Rust port was free to diverge. Either hold everyone to the original design or let everyone redesign.

Compare first passes and tuned versions separately

The first-pass comparison answers “how good is the agent out of the box?” The tuned comparison answers “how fast can this get?” Both are useful. Mixing them isn’t.

Measure what users feel

Throughput on cached reads is easy to measure. For a chat app, you also care about writes, latency under load, and whether messages actually arrive.

Publish the method with the numbers

Commit counts, prompts and tuning steps should sit next to the chart. Otherwise readers can’t tell what’s being compared.

What this means for agent-led rewrites

DHH’s premise still deserves attention: agents make rewrites cheap, and how well agents write a language out of the box matters. But “out of the box” has to mean the same thing for every option.

If you’re planning to have agents rewrite part of your stack and want to compare options fairly before committing, that’s work we do. Book a call.

Rust logo © Rust Foundation, used under CC BY 4.0.

Have a project like this?

We do this work for a living.

A 30-minute scoping call with the engineers who would do the work.

Or email contact@axiointelligence.com and we’ll reply.

Keep reading