What percentage of websites serve 1 mil or more requests per hour, .01%? .001%? Meaning Rails is going to be performant enough for 99.9+% of projects, and for those projects it would have been a mistake to trade dev time for performance you’ll never need.
A SPA backed by rails is probably going to make at least 10 requests on page load. So in terms of actual traffic, 100k page loads during a peak hour. Assume a roughly linear peak increase/decrease and we've got roughly 1M page loads per day. 30M page loads per month.
How many websites have 30M (non-unique) page loads per month? After some rough scouting on Alexa ranks, I'd put the over-under at probably 10k US sites, and 50k worldwide. Assuming Alexa has 50M sites, then 0.1% of publicly facing sites serve that much traffic.
Rails is used often on private, internal sites and tooling. Those sites wouldn't come up. That would definitely skew the 0.1% number.
Not making a huge argument here, I just started down that analysis path out of curiosity and figured I'd share it.
Since 1.9 you can use real OS threads to achieve parallel IO, and certain parallel computations which can proceed without holding the Global Interpreter Lock.
JRuby offers completely unrestricted threading with a single process, plus a 3x performance boost, plus the advantage of an incredible amount of work put into their VM and GC. It's a really underrated option these days.
The problem with forking, is MRI Ruby is unaware what memory is actually inherited by forking, so eventually it causes the entire heap inherited from the parent to copy into the child.
I'm actually working on a patch to fix this. The solution is simple, just don't mark, collect, or allocate into inherited pages, but the implementation itself is fiddly.
What's really exacerbated this, is that most Linux distros now have Transparent Huge Pages turned on by default, and flipping a single bit in inherited causes a 2MB copy instead of a 4kb copy!
The bigger issue is heap fragmentation. Lots of inherited pages have a couple of free slots that Ruby will happily consume, effectively causing you to pay a 4kb copy for a 40 byte object.
This means allocating a few hundred objects can cause basically the entire heap to copy. Combine this with Transparent Huge Pages, where flipping one bit causes a 2MB copy rather than 4kb, and a few hundred object allocations can cause the entire parent process memory to be duplicated into the child.
Aaron Patterson is doing some great work to bring GC compaction to MRI, which will help reduce fragmentation, but it's a huge task.
As someone who develops web apps for startups not in SV, that seems incredibly expensive to me.
That's around 300 requests per second. Assuming 1000ms upper bound on requests, you need 300 workers to handle that load. Assuming 150MB per worker, that's 45 GB of memory required to handle the load. So like... 5 m4.xlarge instances on EC2 (to give redundancy and allow loss of 2 hosts). That's $700/month.
That's not that much. We've got a Rails app that pushes 5000 qps. And to be fair, we just dial up the number of instances and it handles it fine. It runs on over 100 instances. It costs us around $10k/month. Not the end of the world, cost wise, but we have multiple Go services that handle similar levels of traffic and run on a dozen instances. Additionally, deploys take a long time (rolling restarts plus health checks on 100 machines takes time).
Moving to Go (or Elixir) allows us to handle far more requests per unit of hardware. While latency would indeed improve, it's not the primary motivator for us moving away from Rails.
I haven't even mentioned the websocket story on Rails. That's a whole new can of worms.