Ruby Scales, and It’s Fast – If You Do It Right
engineyard.com
engineyard.com
Rather, the trouble with Ruby (and Rails) is that you end up having to implement these optimizations much faster than with a lighter-weight setup (like PHP on top of a vanilla database, with no ORM).
Hence all the discussion about your "stack", middleware, load-balancing, front-end servers, merbs, mongrels, passengers, and all the bewildering variety of gems required for the care and feeding of a production app. Rails developers write about armoring their app with all this extra stuff in a way reminiscent of MMORPG players equipping a character for battle.
It's a legitimate trade-off, and many people seem comfortable making it. But posts like this sidestep the issue. It's not that Ruby can't scale, is that Ruby makes you fuss over scaling right away.
I think the key is that developing the app and scaling the app can be separate tasks. If you do it right, for the lion's share of your app code is still focused on the app, and all the caching and whatnot is handled elsewhere. In PHP, if you had to use memcached it would be a massive change that would touch every corner of your codebase. In Rails, you'd use a plugin and maybe a few filters and you'd be good to go.
If I were to build the same Web site for the same audience and expected traffic using Rails and Sinatra, would using Sinatra (as compared to Rails) reduce the need for what the OP described regarding caching, load balancing, and other methods of increasing performance?
Perhaps it would, as would using Ramaze, or simply writing targeted Rack middleware, but the gains from using lighter tools such as these, as compared to Rails, is that you lose out on using many pre-existing libraries. And while Sinatra and Ramaze are faster than Rails I'm not so sure that they are so much faster that you'd see a big difference in trying to support heavy request loads.
That said I still approach Web apps with the intent of using Ramaze because of it being light, very fast, and feature-complete, but if I find that there are some requirements that are well-matched to some existing Rails extension I'll take that route.
My understanding is, however, that if the site is already simple, you may wind up not needing to do these improvements in Sinatra.
Initially you can simply install Apache and Passenger (aka. mod_rails). With PHP most people use mod_php.
It is true that hosting rails apps was previously (before passenger) not as easy as mod_php.
With PHP, people discuss "the stack" too. Here's a post about scaling Joomla (written in PHP) discussing using FastCGI instead of mod_php: http://www.joomlaperformance.com/articles/webcasts/why_mod_p...
Half of the article can be reduced to saying that ruby is fast when you don't run it (e.g. through caching), and therefore ruby is fast. That's a fallacy.
Note that I did not use Mongrel, evented_mongrel, Thin, or anything else sophisticated as the container for the application. It was just webrick, and it was just a single instance of webrick [.. benchmark done here, gets ~35rps ..] OK. I mean, that’s not horrible. Redmine isn’t a lightweight app, and that’s over 2.5 million requests a day on a single process.
Of course, everyone's idea of scaling and what level of requests is reasonable is different, but there are plenty of sites turning over big bucks doing less than 35 requests a second.
Unoptimized Ruby can "do" on modern hardware - even if it's less than ideal. After all, back in the late 90s, even top sites were running on hardware 10-20x times slower than now. So even where Ruby is 10-20x slower than the alternatives, you can still get 1990s enterprise level performance out of it ;-)
ab -n 10000 -c 1 -C '_redmine_session=9ec759408f1ae3c6f919e50baba5a3dc; path=/' http://127.0.0.1/
Requests per second: 2839.37 [#/sec] (mean)
Time per request: 0.352 [ms] (mean)
Time per request: 0.352 [ms] (mean, across all concurrent requests)
This is an extremely unrealistic workload. It's the best possible scenario for your caches. Yes, he says he was also browsing and editing the site at the same time, but that's still nothing like modeling the real effects of cache invalidation & overflow from many concurrently users.But the thing that really irks me is the discussion of caching reverse proxies and partial page caching. Those optimization techniques are language independent. While I came to the same conclusions about usually needing these with Ruby, I fully recognize that it's much slower at running complex application logic and doing in-memory operations than other languages like PHP, Java, and even Python.
Instead of arguing that Ruby isn't slow (because it is), I would have argued that the time to build and debug a Ruby app is less than it would have been using other languages. Extensive library support, an active user community, many great tutorials / code snippets, no need to compile, and a pretty flexible syntax make Ruby great for quick development. But let's not pretend we can have our Ruby cake and eat it too.
Rails as a framework may do some inefficient things, and I've heard that the next version of rails will address many of these inefficiencies, but as a language runtime Ruby isn't any sloppier performance-wise than PHP and might even already be better at this point.
1) "Ruby Scales, and It’s Fast" makes a point of talking about MRI not Yarv.
2) The fastest of those PHP programs relative to Ruby 1.9 (n-body and mandelbrot) don't seem to make any use of the PHP standard library - which undermines your "library is written in C" point.
3) If you look at the quad-core measurements you'll see PHP but you won't see Ruby 1.9 or MRI because (unlike PHP) no one has contributed Ruby programs that can make use of more than one processor.
http://shootout.alioth.debian.org/u32q/benchmark.php?test=al...