How This Post Was Made
Prompt (blog repo): “a reader suggested investigating if Ractors might be an alternative to the Nodo setup written about here: https://trevorturk.github.io/cheaper-than-staying-in-ruby/ – I dispatched research in the web repo and it created a report here: https://gist.github.com/trevorturk/cb04379495bb9ca72856c7245de198e3 – please review, collect code samples from the tmp files etc as needed, and create a pr with a new post about this experiment and the results – remember to ELI5 and keep it Simple English. the gist I pasted is the output from an AI session which is not really meant to take verbatim, treat this all as input and do your best to draft a nice, human-readable post”
The benchmark itself ran in an earlier session in the web repository on 2026-09-03. Those prompts, with the reader anonymized, were:
Prompt 1 (web repo): “from a blog reader, an interesting idea I’m wondering if you can bechmark: [a reader] [11:31 AM] Can you do this in a ractor? https://trevorturk.github.io/cheaper-than-staying-in-ruby/ Trevor Turk [11:36 AM] you mean, instead of Nodo, call the Ruby stuff within a Ractor? [a reader] [11:37 AM] Exactly [11:38 AM]I dunno if the Ruby part is slower too than in JS, but that sounds like the perfect use case for a ractor: a complex function with simple input and output Trevor Turk [11:39 AM] hmm yeah, lemme ask Claude if it can benchmark and consider it [11:40 AM]tbh in my case the Ruby astronomy stuff isn’t great except for that Astronoby gem [11:40 AM]but it would be fun to see anyway – the idea would be to use Astronoby instead of Nodo to avoid the JS/Node depenedency and keep in Ruby where possible, without blocking CPU. see related work and blog posts about how we benchmark and save CPU. see ~/Code/trevorturk.github.io for post content”
Prompt 2 (web repo): “make sure to dispatch research into Ractors, especially with their recent improvements in the newer ruby versions”
Prompt 3 (web repo): “still running?”
Prompt 4 (web repo): “still working?”
Prompt 5 (web repo): “can you make this a blog post in ~/Code/trevorturk.github.io? I can take a prompt over there if easier, but I would like to do a blog post about this topic. we’d want to anonomize [the reader] so it’s just a “reader” of the blog. see https://github.com/trevorturk/trevorturk.github.io/pull/67 for some more context about the conversation I’m having. we won’t be able to copy the prompts I provided verbatim because we want to anonomize [the reader]. give this some thought and consider how best to handle. another idea would be to create an issue in the web repo that’s anonomized and provides as much detail as the blog post system would want, then I take a fresh session in the blog repo and kick off with a reference to the gh issue you create now? wdyt?”
Generated by Claude Fable 5.1 using the blog-post-generator skill. Inputs were the research report the web-repo session wrote (a gist, treated as notes rather than copy), the probe scripts and result files it left in tmp/benchmarks/astronomy_ractor/ in the web repository (astronomy_ractor_probe.rb, the three yield probes, run_all.sh, the three result JSONs, and the pool-2 crash log), and the earlier Nodo post for the background. The two Ruby bug-tracker links were checked against bugs.ruby-lang.org before being cited; both are open and titled as described. The Ruby research pass in the web session ran on Sonnet; this post’s claims about Ruby 4.0 and 4.1 come from that pass and the two bug reports.
Judgment calls: the post opens on the reader’s question rather than a product framing, and the reader stays “a reader”. The three code blocks are trimmed from the probe files. The pipe probe keeps its shape but uses lambdas instead of a top-level method definition, and its output line is representative rather than pasted from a run. The worker excerpt keeps the sun calculation and elides the moon and twilight lines with a comment, and drops the pool and the adapter’s time-formatting step. The shim is shown nearly whole because the three workarounds are the finding. The results table drops the sequential-phase ticker column and the setup-time column from the research table to fit the page; the numbers shown are copied from the result JSONs. One number the post does not use: the Ractor backend’s 8-fiber call mean was 35 ms with a 26-second maximum, because the benchmark’s pool hands a freed worker straight back to the fiber that just released it, so the last fiber waited through the other seven. That is a fairness bug in the probe’s queue, not a Ractor finding, so the post cites the p95 and the throughput. The 114 MB Node child is reported as measured, with the gap from the earlier post’s 71 MB noted and left unexplained. The pool-4 crash log on disk is empty, so the pool-4 crash is stated on the strength of the research report’s account, alongside the pool-2 log that does show the error. The practitioner writeups the research pass mentioned (a Shopify post and a RubyKaigi talk) are left out because they were not checked.