Hacker News new | past | comments | ask | show | jobs | submit login
Ruby has been fast enough for 13 years (signalvnoise.com)
232 points by ingve on May 16, 2016 | hide | past | favorite | 179 comments

I work at a dev shop and we've been developing web apps for 10 years or so. We've run through PHP, Rails, Node, Python (Django) and lately Go. For the types of apps that we develop, web apps, or perhaps web apps with an API. We have found that ruby/rails is our fastest and happiest combination. It is the slowest combination in terms of code execution speed, but in terms of speed of development and developer happiness it Just Works (tm) and allows us to get reasonable code developed at lower cost. We deploy many sized apps from tiny one server apps to small/mid sized apps with 100k users, but we've never found the speed of Ruby to be a big issue - usually it is everything else, testing, maintainability etc. If speed is an issue we've always been able to work around it without too much difficulty, and these days if we know we will need the speed or scaling we'll resort to Go, but we find that our development time increases somewhat.

The last two apps I have inherited have been in Python (Flask and Django). If they were slow, its because they were poorly written (one page makes over 1000 database calls - it could be done in less than ten). Sort all that crap out before worrying about the language.

I can't emphasize this enough. I'm always blown away by how quickly engineers will chalk a slow application up to the language it's written without even doing a minimal amount of profiling. In almost every case it has been severely limited by waiting on a massive number of backend calls, DB reads, system calls, etc and became orders of magnitude faster after fixing those silly mistakes.

profile profile profile before you waste a ton of engineering effort on a rewrite that may buy you absolutely nothing.

I'm always blown away by how quickly engineers will chalk a slow application up to the language it's written without even doing a minimal amount of profiling.

The more things change, the more they stay the same!

I now install AppNeta TraceView [0] whenever I launch a site. The free plan is fine for initial profiling and it's useful to see what matters under a production load. And the paid plan has proved itself.

NewRelic is similar, but I find the TraceView interface much much better.

0: https://www.appneta.com/products/traceview/

In a talk once I heard web applications described as "database skins." Maybe it's hyperbole, but the general point seems sound - most web apps are CRUD, and the slow point in most applications is IO. I suspect not doing dumb IO is 9 times out of 10 the solution to performance problems.

That said, working against oracle databases with Django is slow as all get out. Something about the driver requires numbers to be converted from number to string back to number, while calculating whether it's an integer/decimal/whatever. Simple queries returning 1000 rows could take ten seconds. I spent several days running that down. The analysts at my shop blamed django, which was pretty unfortunate.

  > I heard web applications described as "database skins."
Not a bad description.

  > the slow point in most applications is IO
The slowest part of web apps in my decade of experience is the database, yes, if that's what you mean by IO. Reading and writing files, also IO, is very fast though. A database can be very fast too (I've mostly used Postgres). Or it can be dog slow.

It's just like how some programmers are 100 times better than other programmers. One SQL query is 100 times faster than another, and both get the same result. And it's not usually something simple like adding a column index. Usually it's a matter of a sub-select or some other squirrelly way of combining tables or aggregating a result.

I wish more programmers learned SQL --- I mean really learned it through and through --- than concentrated on the latest fads.

> I wish more programmers learned SQL --- I mean really learned it through and through --- than concentrated on the latest fads.

And miss out on all the coffee breaks afforded by programmers just looping over entire databases in a horribly inefficient ORM ? Because all this condition abstraction in the ORM is really hard to use ...

Don't worry though : they're optimizing it. I hear they're upgrading to run the loop in 100 threads instead of just one. Surely that will accelerate things a lot !

And if that doesn't work, we always have memcache, don't we ? Also we can now use cloud databases to spread the load, surely that'll help (I'm looking forward for the first double-digit page refresh, measured in dollars)

(Having worked years for hosting providers where 20-30% of my job was making PHP/Python/Ruby/sometimes even Java applications run faster, and achieving 50x improvements on a regular basis, this had to get off my chest. And yes I've seen people implement mail address lookups by iterating over the ORM-provided collection ... and then show 50 mail addresses, wondering why the page load time was bordering on 3 digits when measured in minutes. Not even just once)

Maybe part of these frameworks (Rails, Flask, etc.) reputation comes from newbies doing a lot of database calls because the framework makes it easy for them to do it.

Edit: More clarity.

Django is probably pretty bad for this. The ORM is easy to use for easy stuff, but trying to write efficient queries with it takes a fir bit of practice.

I work at a dev shop and we've been developing web apps for 10 years or so. We've run through PHP, Rails, Node, Python (Django) and lately Go. For the types of apps that we develop, web apps, or perhaps web apps with an API. We have found that ruby/rails is our fastest and happiest combination. It is the slowest combination in terms of code execution speed, but in terms of speed of development and developer happiness it Just Works (tm) and allows us to get reasonable code developed at lower cost.

This reflects what devs saw in Smalltalk. Business apps ran with sufficient speed on 486 CPUs with interpreters and relatively primitive JIT VM. Business apps were typically bound by I/O to databases and other back-end servers. This didn't prevent bad developers and pointy-haired bosses from blaming Smalltalk execution speed. That was almost never borne out with profiling and where it was, judicious implementation of a particular algorithm in C/C++ usually solved it with a minimum of fuss.

If you have do just simple development (web or otherwise) at a small scale then your language's speed indeed doesn't matter very much.

But I think people still underestimate how much development isn't that. Most startups involve things that need to scale now or things that will need to scale. A lot of scientific development need complex algorithms. A significant portion of corporate development needs speed because it's operating at scale or because it's one piece of a long pipeline of import/export applications etc (another portion of corporate development doesn't need speed but good luck finding the discipline to get your manager to distinguish the two cases). And there's embedded and various other things.

"Don't worry about speed, we're just prototyping here" is a saying that always signals danger - a large organization often will want to deploy whatever monster once they know it works.

So really, it seems like Ruby is indeed great for apps for medium-sized brick-and-mortar business wanting a web presence and there is a whole lot of that happening. However, Ruby being inherently slow in multiple dimensions means it's dangerous for many other use cases (dangerous because of the "it works? Why not keep using it" factor and the danger being you'll wind-up using after its slowness becomes a real headache).

Medium sized brick and mortar companies such as Github, AirBnB, Shopify, Basecamp, Groupon, 500px, Capitaine Train (who just sold for 200 millions) and tons of other companies. Helped Twitter get off the ground as well. Now some of them might have moved some of their stuff off Rails/Ruby, but never prevented them from succeeding. It might actually have helped them iterate rapidly in the first few years. The idea that Ruby (or any other language for that matter) is only good enough for some scale doesn't actually translate into reality.

Helped Twitter get off the ground as well. Now some of them might have moved some of their stuff off Rails/Ruby, but never prevented them from succeeding.

I can only answer by parable. Start from the point of view of a group of carpenters asking "is cardboard strong enough to build houses from" and you may a consensus until someone chimes in to say "but a lot of people have made a lot of money selling cardboard houses that survived just long to let them gather investors and money for building real houses." Sure, that may well be true but it's really going to change the view of carpenters.

Except in that parable, Twitter doesn't sell cardboard houses, they used to live in one.

And that cardboard house provided enough shelter for them to survive and at some point, go to the bank to get a loan for a bigger, sturdier house. I understand that Ruby can be an issue at some mega-scale, I've experienced how slow, memory-hungry and not a concurrency natural it can be. But the thing is, for 95% of the people building businesses, they don't need mega-scale. They just need enough. And Ruby on Rails provides just that. It's fast to build a platform with, it's easy to think about, it has a huge ecosystem and it's worked for a lot of people.

And that cardboard house provided enough shelter for them to survive and at some point, go to the bank to get a loan for a bigger, sturdier house.

The owners of Twitter never had to worry about the shelter offered by Ruby-on-rails. The original system architect and his team hardly found shelter since he was replaced along with Ruby-on-rails.

CPU in the web layer is just not the bounding issue in the vast majority of web apps: network access and query optimization are the bad ones. Where you have big-data like stuff going on, you can and should kick out to a job-processing model based on whatever technology you'd like.

From what I see in our perf logs, a faster string concatenation layer in ERBs would be the place where rails could save a lot of CPU cycles, but it really wouldn't matter except for very large tables, and I use intercooler to keep them relatively small w/ ajax paging or infinite scrolling, depending on the UI.

Whenever I read articles about Rails performance I often think about the saying from the early days of Twitter, "Rails doesn't scale". However as most of the comments have said here, the biggest factor that typically affects an app is I/O.

There are plenty of large companies that run Rails and for most up and coming startups Ruby on Rails is probably enough to validate your idea.

You know what's fast? Learning Ruby. You know what's also fast? Rails development!

I've tried Golang and played around with Node. They're fast, sure. The respective frameworks just don't compare.

Ruby (and Rails) scales just fine for 99.281% of things. You just need to throw money at it.

And that's a great thing.

A business's success will never depend on of the speed of a language or framework. It just doesn't work like that. What matters is how quickly you're able to iterate and evolve a product.

Ruby (and Rails' ecosystem) allows me to not have to reinvent the wheel for mostly everything. Authentication? Devise. ORM? ActiveRecord. Background processing? ActiveJob. Caching? It's there.

Want awesome front-end performance without having to basically rewrite your entire app and learn another framework and manage its dependencies? Turbolinks, and it has matured beautifully.

Basecamp has its performance anecdotes written in history that we can all reference. And Basecamp also has had great success.

Point being is that a business is a business. The speed of a product cannot and should not be blamed for how successful a business is or isn't.

I love you, DH2, and thank you Matz. I love you too.

>>Ruby (and Rails) scales just fine for 99.281% of things. You just need to throw money at it.

>> Basecamp also has had great success.

Basecamp is a great SAS business, you can tie utilization to revenue. Throwing money at the scaling problem (horizontal) is completely realistic in that scenario.

If you can't tie utilization directly to revenue, if your a pure service like twitter, or an online store with a bad browse vs buy ratio ruby is a BIG liability.

So is ruby fast enough? It depends. Its a business decision, not a technology one, and one I would have a hard time justifying for a lot of startups.

A few years ago my side project (and my second ever ruby/rails project) unexpectedly became quite popular.

Last couple of years it's been doing about 50,000 (user facing) api requests per second during high load, with almost a million concurrent users. It's 99% rails.

We (me and a second guy) have ran this system on ~10 (cheap) servers, five of which run the actual rails app. The rails app has probably been the easiest component to scale for us. We obviously do some caching - but it's not like our database could live without that caching anyways.

And even though we have been an ad-financed bootstrapped company the hosting/hw costs has been very manageable. There are probably many valid reasons to chose something else than rails, but I wanted to share my experience w.r.t. making it work for our non-SAS needs.

I love stories like this, as they can be Illuminating, and I'm curious for more answers.

1. profitable? Is it your day job or Side job or a "lifestyle business", Pays for my beer...

2. I would love a number next to cheap ($5? $20)

3. Where are you located, and is that the market your serving.

Because I live around Silicon Valley, my perception of what your saying might be really different from what it actually is... is cheep $20 a month, or is it $5?

1. Employing twenty people and making a profit.

2. Per app server we paid less than the cost of a macbook pro. Between 0.001 and 0.0015 USD in hardware costs per thousand ad views, which makes it irrelevant to the company bottom line.

3. Europe, global-ish market.

> you can tie utilization to revenue

This is a critical aspect.

If it's purely ad-driven, you probably have very little money coming in for the number of pages you crank out, so you need to optimize them a lot.

If you're charging for your app - which you should be in a lot of cases - then something like Rails is likely ok.

The latter case is much more likely outside of Silicon Valley/VC-fueled startups.

> If you're charging for your app - which you should be in a lot of cases

I think it really depends. Many of the most successful businesses thrive purely on ads. Also you'll have to consider which market you're targeting. In the US many people maybe are used to paying a reasonable amount, but in many developing countries people just won't use it if it's a paid app.

Even then I think it is a hard sell.

Lets say that the gain you realize from writing in another language is 10% of your infrastructure costs. It might not matter day one. At some point that will represent a significant sum of money, in either absolute or relative terms.

Premature optimization and all that... Worry about it when it looks like it might matter.

Worry way, way more about building the right product at the right price for your customers, and adding the right features.

Hardware is cheap. Developers are not.

precisely the reasons why I use Django.

Didn't DHH write this post a few years ago about how layers of caching were needed to get Basecamp to perform at an acceptable speed?


Computers are amazingly fast these days, but 99% of all CPU cycles go to waste because of this "slow is fast enough" mentality.

You would need caching regardless of the language. 99% of cache calls for web sites serve to offset the delay waiting for database calls to return, as opposed to any slowness with the programming language.

The problem for most startups is that they're not even sure that the CPU is spending its cycles on the right thing.

A language/framework that helps you figure that out faster is superior to one that is slower to code with. And Ruby/Rails are pretty good from this point of view.

I'll add: perhaps the time will come when there's something that's equally adept at being light on its feet, and is also faster. Elixir/Phoenix look interesting from that point of view. But even there... Erlang is certainly not the fastest thing out there.

Web applications are not CPU-bound, they're IO-bound. So in this scenario caching is used to reduce the amount of requests to the database.

This can speed requests up but more importantly it allows you to more easily scale out horizontally.

The rise of SSDs has changed the degree to which web apps are I/O bound. So the conventional wisdom from several years ago doesn't necessarily still hold. Check out this blog post from the developer of Mailinator:


> Web applications are not CPU-bound, they're IO-bound.

Is that a fact? I'm not sure anyone has ever shown numbers to back it up. It would be an interesting piece of work to do. I can imagine it's true, but I'm not certain.

I think Rap Genius did a blog post ages ago about being hosted on Heroku, and they said that something like 70% of time was spent inside the Ruby interpreter, not waiting on IO. So modest improvements in the speed of Ruby will have an impact on their bottom line.

>Is that a fact? I'm not sure anyone has ever shown numbers to back it up.

What? I've seen tons of profiling posts and articles showing just that thing, and it's the same thing I've also seen forever on my servers' stats. I'm obviously talking about the majority of web apps that are using DBs and doing some kind of CRUD work -- not video processing services et al...

This is the blog post I was referring to http://genius.com/James-somers-herokus-ugly-secret-annotated and the key graph http://images.rapgenius.com/75aa2143d3e9bf6b769fc9066f6c40c8....

Is that non-typical? Or am I mis-interpreting the graph? (Genuine questions, I've never done any web app operations.)

That graph still shows time to process/respond, not CPU utilization.

From the article the slowness is when "a dyno is tied up due to a long-running request" -- so, we they are probably still talking about slow IO operations, and servers running on the dyno that are not async to free it up in between.

From Heroku's one optimization page: "Most applications are not CPU-bound on the web server".


(And Heroku might be an outlier in having high real-cpu use too, as they tend to over-provision).

But the graph shows time in waiting on web requests (dark green), time waiting on cache (teal), time waiting on the database (brown) and time queued before the interpreter gets the request (light green) separately to time spent running the Ruby interpreter. It's a cumulative graph.

So if the IO isn't web requests, cache, database or waiting in a queue, what can the interpreter be waiting on? Local files?

It varies a lot depending on type of app. Backend dashboard full of reports? Odds are it will be waiting on complex JOIN's to complete in database requests. More lightweight stuff with mostly simple key'd queries and things like complex views can easily make it CPU bound.

In general it's a useful idea that you're likely to be IO bound, because most of the time when something in a new webapp is too slow, it will be database (it may be a small fraction of overall requests, but the ones that hurt) until you have optimized/cached away your database request and are trying to scale further.

Basically once you've solved the "naive"/early database bottleneck, then CPU and memory very quickly becomes more likely to be a cost factor.

I take a bit of a No True Scotsman position on this. In general, web applications don't need to be CPU-bound: the amount of computation they need to do has a small cost compared to that of the IO they need to do. But not all web applications only do the computation they need to do - some do a lot of unnecessary computation.

For example, there's a painfully slow web application at my company that puts data on a page by doing a straightforward select from a database, and then running lots of nested loops over the data to render the page. It's definitely CPU-bound. If it was written to use a more powerful query, or to use more sophisticated algorithms, it would be a lot faster, and would probably be IO-bound. But it isn't.

I shouldn't have spoken in absolute terms, "primarily IO-bound" would have been a better choice of words.

That said, in my experience this has been the case when it comes to handling HTTP requests.

> but 99% of all CPU cycles go to waste

Reminds me of this tweet which summarizes Ruby quite well:


There's no doubt that by not fully utilizing modern CPUs it is giving a serious advantage to the future prospects of languages like Elixir which make using concurrency as easy as using Rails or Go, where performance is baked-in. It's not so much about is Ruby good enough but why use Ruby in the long run if there are languages offering similar benefits but with better performance or good concurrency primitives?

Having support for the latter is not a detriment to early stage projects using the languages (this isn't about Java/C++ vs Ruby any more...), but later on lacking it will

In reality you run your site on multiple workers and they share the CPUs.

Ruby performance on par with Python, PHP etc. Rails is slow but at same time it's faster than like 80% of all the PHP frameworks. So i'd agree with DHH - not the issue at all in most cases. Someone can choose different framework for other reasons than plain requests per second. In case of Elixir/Phoenix it's things that Ruby/Rails can't handle properly, like

* websockets & realtime stuff. (Rails 5 added that, i know, point still valid)

* dev mode experience. rails startup time is slow enough to add bandaids like "spring" in default installation.

* sort of "magic" that actually hurt developers

> * websockets & realtime stuff. (Rails 5 added that, i know, point still valid)

Seems a bit dismissive. It's not like Elixir/Phoenix have really been mature for all that long either. (Especially if your definition of "maturity" includes a broad selection of userland packages/gems.)

> * sort of "magic" that actually hurt developers

It's not just this comment, but I don't understand why "it's magic and that's bad" seems to have been accepted into the encyclopedia of Facts About Rails™. I still have yet to see a particularly good argument against CoC[1]; it boosts productivity and teaches developers to write concise, consistent, expressive code. All good things in my book.

[1]: http://rubyonrails.org/doctrine/#convention-over-configurati...

Counterexample: just yesterday I spent nearly two hours trying to understand why a bunch of records was not being updated to database. Turns out that when attributes on already persisted records get assigned in particular sequence, ActiveRecord suddenly decides that there are no changes to be saved. Swap two calls, everything suddenly works. And there was nothing to help me to get to that solution, just groping in the dark and trusting my years of RoR development for a general direction.

Rails is great, and I've been productive in it for a long time. But the complexity (some would call it bloat) is real, and there are nasty edge cases. And when you stumble upon one, well, good luck.

I'd like to hear more about this. Is it possible you could share an example that demonstrates what you're talking about? Thanks.

That definitely sounds like it should be reported as a bug.

> "maturity"

maturity is many-dimensional here.

* userland packages - yes, sure. erlang/elixir ecostystem is not mature as of yet. It works, it nice, but you can't find everything you need (including e.g. blog posts and SO answers for every possible question).

* On other hand, erlang base brings stability, instruments to solve every possible _production_ issue out there.

* Phoenix itself is has same mixed aptitude - it's pretty new and, at same time, written by core rails dev and therefore has many design issues fixed from start.

> "it's magic and that's bad"

IMO it's not the magic that hurts but overtwisted internal logic where you can't figure out how it works exactly (and yes, Rails became pretty complicated software). Keeping things simple (at least "mental model" of things) is damn hard :( Phoenix is basically == "rewrite from scratch to reduce complexity and fix things that can't be fixed without starting from scratch"

> convention-over-configuration

i like that! Also, both Rails and Phoenix doing it right. 90+% other frameworks failing miserably :(

This argument falls flat to me. All of Ruby's competitors ran on similar servers 13 years ago as well (except for a few that didn't exist yet).

All of them have optimized and improved their speed since then.

In 2003, it was expected that web pages have a bit of a delay before loading. In 2016, it is not. Ruby has not yet adapted.

I'm really not subscribing to your argument that every other language got faster and ruby didn't. Ruby performance has increased significantly since 2003, and ruby has had concurrent IO using threads since 1.9. Python shares the GIL problem, and Node doesn't even have threads (have fun debugging events!), so you're not going to add much water to the argument in that department.

Additionally, computers got much faster and have many more cores, allowing for additional process concurrency. This is an argument for me to move to higher level, more abstract languages, not to race back to lower level languages because "they're fast". If anything, ruby/js/python aren't high level enough and could be slower but more productive. I'd choose that over raw performance for the vast majority of my needs.

Additionally, Rails benchmarks might show ~100 hits per second (that's 8,640,000 hits per day per process, do you actually get that much traffic?), but I can get thousands of hits per second running Sinatra. I still think Rails is plenty fast, but it's silly to blame a language for a framework.

Ruby has for years been a victim of FUD, opinions on it's performance that seem to have been derived from fuzzy stereotypes rather than actual information. I think that's what the author is frustrated about, because that's the one thing I'm pretty frustrated about too. I'll be the first person to abandon ruby when a better language comes out for my needs, but I've still never seen it.

Every language that supports threads has "concurrent IO". That's what threads/processes are for.

However, threads will never help you in an IO-bound system (unless you own some kind of thousand-core CPU with an equal number of OS threads). Threads will simply block at the first waiting IO call until you eventually run out of threads. Node.js from the beginning was built for non-blocking IO, as are several Python frameworks (e.g. Twisted, or more recently, Tornado), thus the need for more than one thread of execution was typically unnecessary (again, provided the bottleneck was IO).

Threads can absolutely help you in an I/O-bound system where concurrency is possible and desirable - specifically, in a RAID environment. (You can't max out RAID throughput with a single thread - try it.)

Most of the pages I visit now load slower than in 2003. The server language has nothing to do with it, and is not the bottleneck in 99% of the cases.

A typical request to our rails app will be served in under 100ms, with the majority of that time being data access. Even the fastest Go app is one bad query away from a horrible response time.

CPU in the web layer is not the bounding issue for most web apps.

Are you suggesting that Ruby has not improved its speed? Are you suggesting that Ruby is too slow for the web?

No. His argument is "It was fast enough in 2003 and it's gotten faster, so Ruby is fast enough now." He repeats the "it was fast enough in 2003," 3 times in the article. I disagree with the premise that fast enough in 2003 is fast enough now.

Adding a vague "it's gotten faster" is not sufficient to mean that it's fast enough for 2016.

It may or may not have improved enough, but either way this argument does not prove that it has.

Something that was fast enough in 2003 is sufficient to say that it's fast enough to 2016 - even if nothing has improved, it's going to be an order of magnitude faster simply because of hardware improvements.

There are some technologies that were impractically slow in 2003 but have become 'fast enough' in 2016 either by improvements of tech or just by having more cpu/ram/gpu power - but not the other way around.

The point DHH is trying to make is not that 'Ruby is fast', but that 'Ruby is fast enough' for what people generally need. If you're building some whatsapp-esque messaging platform, then yeah: ruby is not fast enough; but for a majority of the uses that Ruby is used for (building web applications) it is indeed fast enough to build enterprise-level applications.

While DHH says that CPUs in 2004 were fast enough to run Ruby, while CPUs have relatively stayed the same speed the call stack and complexity of Rails has probably doubled or triple in that time period.

Ruby's performance does matter. In 2016 you can't call yourself a language optimized for developer happiness when it takes seconds or minutes (in the case of some Rails apps - Hello routes.rb!) just to start up.

Help me understand how, in your workflow with Ruby on Rails, a few second delay in staring up the application hampers developer happiness?

I ask because in mine I start up the application very rarely, say when changing a gem, initialization or configuration file. All other times my changes, in development, are automatically refreshed. Hence I rarely start and stop my development system. Of course I am running my development locally. If you were actually deploying your ENV out to some servers continuously for every change then that would be annoying, yet how much of that delay is do to Rails restarting vs doing a remote deploy....

Running specs/tests involves reloading the environment for most people. Spring is surprisingly good for this, but you can still run into weirdness where spring needs to be reloaded due to some sort of state issue.

exactly. Rspec/rails is my favorite vim plugin but I really hate the time I spend waiting for the spec to run after I've typed \s (note: that's the actual key sequence not an indication that I'm being sarcastic).

Most developers have pretty short attention spans and we expect things to be fast. In development on a large-ish Rails application due to the way Rails autoloading works (I heard this is changing soon?) just editing certain files is not that far off from a full-restart. So the "F5 Driven Development" flow is very slow on our app. The Rails app I work on is 9 years old (no rewrites, go us!).

We've tried to use pre-forking preloaders like Spring but we found ourselves force killing Spring more often than it was useful for us.

EDIT: Performance is complicated and can be a sensitive topic so I'm going to elaborate. While dev restart/refresh times are annoying, the real elephant in the room are Rails test suites. We (and many other places I've worked at) rightfully use our test suite as a signal of when to merge and when to deploy. This means the entire suite (~4000 tests - it's a big app!) needs to come back as passing before we will merge a branch that can be deployed. Our current test suite takes about 40 minutes to run in a single process (more on this later) if the planets align.

Here's a list of a few things I've done in my career (I'm very grateful Ruby and Rails have given me a career, btw) to get around Ruby and Rails' performance gotchas:

- Caching logic so complicated that you would think our business domain is actually caching and not our real business.

- Converted a test suite from TestUnit to RSpec (it was fashionable) and then finally back to MiniTest.

- Stopped writing the type of test that is by far the most valuable (End-to-end browser specs) for all but the most important features due to how slow these types of tests are and the amount of false negatives they produce.

- Tried the whole shared_connection.rb[0] trick to share a DB connection between feature spec thread and Rails server threads for transactions in feature specs. It's buggy and made our test suite worse off.

- I've gone back and forth between PhantomJS and capybara-webkit more times than is healthy.

- Wrote code to spoof the User session in the above tests so we didn't have to browse to login_path all the time.

- Set DEBUG_ASSETS to false in development (except for when we're editing CoffeeScript files) to reduce the amount of work that sprockets need to do.

- Used our hosted CI's parallel test runner to try and run things faster. Marginal improvement, proprietary, and lots of yucky config files.

- Used Aman Gupta's test-queue[0] to parallelize our test suite under our own control and now we're looking for automate spinning up instances with 8+ CPUs to hopefully get our test suite to run in less than 5 minutes.

0 - https://gist.github.com/josevalim/470808

1 - https://github.com/tmm1/test-queue

Rebuild times for almost any decent C codebase are less than that, and people should complain. Wait a bit longer, lose more feedback cycles.

When I used to do C++ the build time was quite long, of course this was in 2005 using lots of STL, so that is not really a fair comparison. As such do you have any open source examples of decent C codebases? I would actually like to try this out for giggles.

> while CPUs have relatively stayed the same speed

Say what?


You'll notice this does not pick models with far higher core counts. The per-core performance growth may have slowed, but it certainly hasn't stopped.

> Ruby's performance does matter. In 2016 you can't call yourself a language optimized for developer happiness when it takes seconds or minutes (in the case of some Rails apps - Hello routes.rb!) just to start up.

Don't blame Ruby for the complexity of Rails (to be fair, it's not just Rails - a large part of the problem is bundler which happily piles stuff in the load path that causes startup times that grow exponentially with the number of gems)

The increase in per-core performance has still less than doubled in that time span.

That's not what the article I linked to says, unless you limit what you consider to very specific workloads.

I think the main complaint about Ruby is going to become, "it's impossible to install". Used to be a beginner user could install a workable current version of Ruby with one or zero commands from a Linux distro. That is no more.

Less relevant these days with Docker, but yeah, I get your point. There have been a number of posts on HN in the past few months about the complexity of dependencies between gems, and how many of Ruby's performance issues are actually due to these types of dependency issues (your app's performance used to be good, till someone changed a method in a module that another module you use depended on and made it 5% slower, except that module used it 30 times per call, so the resulting code was 50-100% slower).

Maybe/kinda? I used to teach at General Assembly, at at least when I was there adding the layer of Docker for complexity, on top of RVM/RBenv, Rails, etc... was seen as too much.

In my current company, we also haven't moved to Docker. A few people use it for a few things, but I'm not running it yet myself. Definitely not a universal, and I'm actually kinda unsure where to get started with it in my daily workflow.

I've never had trouble installing fairly up-to-date Ruby versions on Linux, but Mac OS X can become a disaster once you get into installing certain gems.

I put this down to Apple more than Ruby, though, since Linux support hasn't let me down in the same way.

docker run -it -v "$PWD":/usr/src/app -w /usr/src/app rails rails new --skip-bundle webapp

...and someone interested in learning ruby as a beginner is going to know (and understand) that incantation how?

I hope your comment was meant as a sarcastic jab lol.

Eh, in the bad old times some big distros thought it was a good idea to not install the Ruby stdlib by default.

It is not harder to install ruby than it has been.

You can type `apt-get install ruby` for ruby 2.3 in ubuntu 16.04

And osx...

`gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3`

`\curl -sSL https://get.rvm.io | bash -s stable --rails --ruby=2.2.2`


It literally doesn't get easier than that. Need Postgres? Postgres.app. Need redis? Probably will install brew anyway, and then `brew install redis`

I'm not seeing OP's argument here. Sure, it's not PHP where zillions of shared hosts are abundant and you can just upload stuff via FTP, and there's no cPanel/DirectAdmin or Fantastico/Softaculous for your WordPress deploy.

But that's a different segment of a similar-but-not-same market.

ah, sorry, I haven't upgraded since the last LTS, which is a mess. You get 1.8.6? 1.8.4? by default, and then TSHTF when you try to install higher 2.x versions.

Posted on the other submission:

If nothing else, I think reminding people that what they're "looking to do" (whatever that is) most likely is something they can do in whichever language they choose, and to somehow shoehorn themselves into a language or a set of languages, not because they have a concrete need to, but because they think they might need to... (Once they start... If they ever get going on it...) is foolish and really does not contribute to execution.

Sometimes it's better to get going in the most productive language you can find for the problem space and make a slow/inefficient implementation with few lines of code, minimizing the risk of bugs, (call it "MVP" or whatever) if only to find out whatever it is you're trying to do. Most languages without suffocating boilerplate will do just fine for this, regardless of their performance.

Ruby isn't fast enough. We're getting 2-20x speedups by switching to Go. (Some things are io-bound waiting on the database, that's the 2x end of the scale, some things we're doing more compute on and that's the 20x end of the scale.)

Are you surprised that static type/compiled languages like Go (or C or C++ or many others) are significantly faster than many dynamic type/interpreted languages like Ruby and Javascript?

If performance alone is important to you (rather than many other considerations like ease of coding, library ecosystem, number of developers who know the language) - you'll almost always do better with compiled languages - especially those with good concurrency support. But the power of many of the dynamic languages is that they provide an ease of coding that reduces the cost of development significantly, especially for earlier stage companies where the benefits of performance may be less important than other considerations.

For many teams I've seen, you can also rewrite the most computationally heavy parts using FFI, allowing you to have the benefits of dynamic languages without some of its disadvantages for computationally heavy work (though it comes at a cost of adding a new language into your stack).

I say this teasingly, but you may want to rewrite your slow Golang codebase to see how much faster performance you could get with C++ (but again, it comes with a cost to your development team - and only your team can decide what tradeoffs to make given the stage of your product/company).

Separate reply because it's a separate topic: Dynamic types aren't the reason for Ruby's slowness either. The Racket code that beat Ruby by 25x in the Mandelbrot benchmark has no type annotations: http://benchmarksgame.alioth.debian.org/u64/program.php?test...

Incidentally, neither u64 nor u32q are being updated -- that data is from before November 2015.

Why did you throw JavaScript in there? V8 is in the same 20x-faster-than-Ruby club that Go is in. http://benchmarksgame.alioth.debian.org/u64/compare.php?lang...

Not as a slight to Javascript, but simply because it is an interpreted language like Ruby - though you're right that benchmarks show a large performance gap. (Javascript has significantly more investment in it, which is partially why it's such a performant language for an interpreted language)

Compare Javascript to many compiled languages, and it's still much slower with a heavier memory footprint (for heavy computation especially at internet scale or for realtime needs like graphics, you'll want to at least consider compiled languages).

But my original point is that performance shouldn't be the primary characteristic you measure a language or framework on, unless it is absolutely critical for your needs and you're fine with the other disadvantages that might bring.

"Interpreted language" is an imprecise term. A language is a language whether implemented in a compiler, an interpreter, or a REPL that includes a compile step.

JavaScript is faster than Go in some benchmarks, and slower in others. In benchmarks where it's much slower, the reason isn't that JavaScript interpreters exist. The reason is design decisions in the JavaScript language that make optimization difficult. http://benchmarksgame.alioth.debian.org/u64/compare.php?lang...

Someone familiar with the V8 compiler might correct me, but I suspect that the binary tree program is slowed by JavaScript object-property access always being a dictionary lookup. I suspect that fasta and reverse-complement are slowed by JavaScript's one-type numeric tower ... everything's a float.

> … I suspect that the binary tree program is slowed by … I suspect that fasta and reverse-complement are slowed by …

Maybe it's the way the programs are written.

For example, binary-trees Go #6 program is no longer shown because it doesn't do what's required.

JavaScript property lookup hasn't been forced into hash table access for probably a decade now.

It's not a surprise, just a counterpoint. We have a big webapp in Ruby, and a bunch of data processing stuff also in Ruby because that was convenient to write it all in the common server side language. But now we have the problem that actually the data processing needs to go faster. Our page load speed isn't great either, but it's easier to try changing out little parts on the back end.

I totally agree, and it's great to hear the backstory of your process, which is typical of so many companies that start with Ruby/RoR and then grow (e.g., Twitter, Github). Here's a question that others might value for you:

Would you have written the app originally in a different language(s) or framework(s)? Or is the approach you chose (start with Ruby then selectively refactor), the approach you still would have taken given all you know now?

What about, probably they couldn't even be here commenting this post if they hadn't started off with Ruby/Rails?

The thing about Go is that being a simple language and not requiring so much of the bureaucracy other statically typed+compiled languages demand means you lose very little development speed (if any) while gaining a tremendous amount of speed, obsoleting Ruby in a huge amount of situations.

The same cannot be said of languages like Java, C#, C++, C or Rust, for different reasons.

As someone who went from Java to Go, i'd say the opposite - i lost a lot of development speed due to the poorer tooling and lack of expressiveness.

I was comparing it to Ruby.

Java has the bureaucracy I mentioned and that expresiveness you speak of is often the biggest creator of technical debt which specially shines when someone else has to work with your code and understand all your different abstractions.

As far as tooling goes, what are you particularly missing from the Java ecosystem? Honestly I have big gripes with Java's tooling, most important of all the language's hard-dependency on big IDEs to get anything done.

I don't really know what you mean by bureaucracy. Is that the same as boilerplate? What bureaucracy does Java have which Go doesn't?

You're quite right about expressiveness being a double-edged sword. I've been lucky enough to mostly work with programmers with the judgement to use it well. I don't think that's rare, but it's not universal.

The tools I'm missing are sane dependency management, and automatic refactoring. Any language where I don't have good automatic refactoring is going to be slower to work with, no matter how wonderful the language itself.

    MakeSureToGetItInPrint importantThing = new Namespace.MakeSureToGetItInPrint(one, two, three);
Dependency management in my experience is not a problem at all in Go. Vendoring might be different but it's not complicated nor strictly worse.

As for automated refactoring, what more would you like to see in the tooling compared to what you already have (renaming)? The death-by-thousand-file-splits that's recommended in Java and for which IDE help is useful, is not idiomatic in Go. The most code you have to write to split a file into two is the keyword `package` and the package name. The rest is just copy+paste and let `goimports` take care of doing the rest.

That's a funny example, because it's rare to qualify a type with a package in Java, whilst it's essentially universal in Go.

Automatic refactorings i routinely use in Java are extracting variables, methods, constants, and fields (including automatically finding and extracting repetitions of the body); inlining the same; splitting and combining variable declaration and use (easier in Go, of course!), adding, removing, and reordering method parameters; correcting declared method return and parameter types based on actual use; extracting superclasses and moving methods up and down type hierarchies (again, not relevant in Go); moving methods to a receiver which was one of its parameters. All the stuff which is the bread and butter of reshaping code. All done in a keystroke or two. Not copying and pasting and then manually following through.

Again, to be clear, i have done Go development. About three months of full-time Go with experienced colleagues. I know what state of the art Go development looks like. It's unambiguously slower than Java development.

We'll have to agree to differ on dependency management.

So would you say that Ruby's ability to monkeypatch third-party libraries at runtime is not the type of expressiveness that "specially shines" when others have to work with your code?

Because I've had to deal with that type of shit before. Java might have a history of AbstractBuilderFactorySingletons, but you'd be hard-pressed to find an IDE that couldn't make quick work of it. Monkeypatched at runtime? Good luck!

I've had to deal with both and monkeypatching isn't the worst thing, because it's static & greppable.

...and you've found the hack. In java land, third party breakage is just as common and countless times I had to decompile random jars to figure out where the bug was, and resort to strace to figure out which jars were being loaded by misbehaving classloaders.

Forking a gem is preferable to monkeypatching, but sometimes this can lead to a chain of forks just to change one line in an indirect dependency, worse than the patch.

No, the worst thing is method_missing. Methods that appear nowhere in the source getting invoked, and they only appear at runtime. You can do similar things with InvocationHandler in java but it gets used far, far less.

Sure, maybe not the worst thing (I don't use Ruby primarily) but just one of the many things where the "expressiveness" of the language itself is can be as much of a boon as it can be a nightmare.

Misbehaving classloaders sounds like a straight up bug, or a lack of standardization around how a classloader should work. That doesn't sound so much like a failing of the language itself, but again, Java isn't my primary language so I'm not entirely privy to the landscape of Java fuckery. :)

Are you comparing Rails to whatever framework you're using in Go, or ruby to go? Because rails is notoriously slow and heavyweight, even for ruby. Sinatra is faster but then you're lacking in features and conveniences that Rails provides, like ActiveSupport and ActiveRecord

Agreed. On non-DB bound things, I've experienced a 50-100X speedup with Go.

My belief is that lack of concurrency primitives is what will kill Ruby, not today, 10 years from now. We're running on momentum alone at this point.

That said every Rubyist should be following Chris Seaton's work chrisseaton.com/rubytruffle/deoptimizing/ with JRuby Truffle+Graal. This is our best change, imo of course, to make Ruby fast.

You should watch the Evan Phoenix talk at RubyKaigi 2015 ("Ruby 2020") https://www.youtube.com/watch?v=QaLvtNpoc5o.

It proposes a very interesting path for Ruby to get way faster, without resorting to the JRuby implementation.

Basically what he's proposing is we could compile all the Ruby Stdlib ahead of time to a LLVM kind of bytecode.

Once you do that, a JIT compiler for Ruby code could perform a way deeper optimization, because the compiler horizon-line will be stretched much further away: the compiler will be able to inspect the Stdlib bytecode and make optimizations to your Ruby code taking all that into account!

This could be a revolutionary approach for MRI, please go see the talk, it's really interesting!

I know that Ruby was broadly a horrible mess in, say, 2010.

For example, the Ruby interpreter never returned dealocated memory to main, it just kept anything deallocated by a program in it's own memory - copy a huge file between machines, wind-up with a

The head of operations of Twitter told me that at one point they were starting and killing ruby processes every minute because of Ruby's huge memory appetites and they not only had to throw huge amounts of hardware at the problem but also throw huge amounts of electricity to keep with the CPU churn.

I'm quite sure that's still the case. MRI will never return memory to the OS. (I am open to being corrected, since it has been several major versions since I verified this.)

It's true in practice but not in theory.

Ruby can't defragment memory pages - if there is an active object in any heap page, it cannot be released back to the OS. Technically, Ruby does release empty pages back to the OS, but in practice, heap pages are rarely completely empty.

> copy a huge file between machines

This doesn't need very much memory.

Sure but just do it with a huge cache. It's not about how to X efficiently but just that when you allocate a huge chunk of memory, the system will not see that memory until the interpreter terminates.

Ruby really needs to put performance on the roadmap as a serious project. The work done on Python, on Perl, on JavaScript especially shows that there's huge gains that can be made if you prioritize it.

Sadly the core Ruby team has been incredibly indifferent and at times outright hostile to projects like JRuby and Rubinius that have tried valiantly to push Ruby forward.

I'd rather not see people use JavaScript, Swift, or C# because Ruby wasn't fast enough for their particular problem.

> Ruby really needs to put performance on the roadmap as a serious project.


> At RubyConf 2015 in San Antonio, Yukihiro "Matz" Matsumoto announced Ruby 3x3. The goal of Ruby 3x3 is to make Ruby 3 be 3 times faster than Ruby 2.

I'm not sure there are any realistic ideas to actually achieve this for MRI though (beyond the one-sentence bullet points in that article). The roadmap needs to have some roads on it rather than just wilderness!

That's speaking as someone who works full time on optimising Ruby, and wrote a PhD on it.

I think the one hope is that Evan Phoenix suggested an idea that would let an LLVM JIT optimise through the Ruby implementation, but this is a full-on research project (he said it wasn't, I'm not sure I agree), and nobody is working on it.

You should watch the Evan Phoenix talk at RubyKaigi 2015 ("Ruby 2020") https://www.youtube.com/watch?v=QaLvtNpoc5o.

It proposes a very interesting path for Ruby to get way faster, without resorting to the JRuby implementation.

Basically what he's proposing is we could compile all the Ruby Stdlib ahead of time to a LLVM kind of bytecode. Once you do that, a JIT compiler for Ruby code could perform a way deeper optimization, because the compiler horizon-line will be stretched much further away: the compiler will be able to inspect the Stdlib bytecode and make optimizations to your Ruby code taking all that into account!

This could be a revolutionary approach for MRI, please go see the talk, it's really interesting!

How is GraalVM + JRubyTruffle going? It's a fast implementation of ruby.


Three times faster is a good start, but honestly, if JavaScript had only come 3x faster than it was in its early days nobody would take it seriously for anything.

Except that JS became that faster because Google invested $ millions on making it so.

Wow, I'm surprised that YARV[1] has no JIT, I thought that might have been part of the reason for the switch to it back in the day (late 2007).

[1] https://en.wikipedia.org/wiki/YARV

He also said in a recent podcast that Ruby 3 will likely take 2 to 3 years to complete so don't bet the future on it.

But they also mention it is 3x faster then Ruby 2.0! Ruby 2.1 and 2.2 actually bought in lots of performance improvement already.

Yes. Rubinius, in particular, should be given more love. I mean, it is one thing to say that Ruby is fast enough for your startup's application supported by lots of memcached instances with a CloudFlare front. It's another thing entirely to have a compiler written in your language, and claiming that that it is fast enough.

I had a lot of hope for Rubinius and that team is all heroes in my book. What a shame that the whole project ran into serious friction due to politics and culture.

Their greatest legacy, the incredibly comprehensive Ruby Test suite, seems to be largely ignored by the core team which is a true shame. http://rubinius.com/2014/12/31/matz-s-ruby-developers-don-t-...

After Rubinius discontinued it as a standalone project, it was adopted by someone else and now lives in the MRI org on GitHub https://github.com/ruby/spec.

That's good news!

The work done on Python, on Perl, on JavaScript especially shows that there's huge gains that can be made if you prioritize it.

What's the work done on Python?

If we're not counting PyPy, and we're not counting Cython, and we're not counting the ease of writing CPU-bound code in C or C++[1] while leaving the rest of your application in Python (e.g., like Numpy and other libraries do), then we're left with:

Releases like Python 3.6[2], where lots of little optimizations are made, give Python a performance growing edge on Ruby.

1. https://docs.python.org/2/extending/extending.html

2. https://docs.python.org/3.6/whatsnew/3.6.html

There's ease in writing extensions for Ruby in C and C++ as well.

Those Python 3.6 enhancements are still going to result in CPython being absolutely crushed by Python 2.7 on PyPy5.

well since he disregarded jruby, you would have thought pypy was out too.

Well, if you disregard the reimplementations, there's no evidence that there's a lot of speedup to be had, either. The core implementations haven't gotten much faster. So I took at least one sensible interpretation.

Even Tcl is faster than (or comparable to) Ruby these days.¹ (Incidentally, Tcl definitely doesn't get enough love for having a very high-quality implementation.) When the stringly-typed language is competitive in performance, maybe you should reevaluate a bit.²


¹According to entirely unreliable microbenchmarks found via quick web searches.

²Not to knock Tcl. I actually love Tcl. One of the reasons I love Tcl is the ease of extending it in languages with better performance.

Anyone running a non consulting firm can talk about maintaining a ruby application across a big development team for a long period of time? The dynamic nature of Ruby has led me to think that it will have maintenance problems compared to say a strongly typed language like java with the tooling available.

Ruby is fast enough and it's a beautiful language with a few warts, just like any language.

Profiling and caching should be the first step to solving an existing app's problems.

Rails is a great framework because it gives developers rules, a simple pattern to follow.

All that being said, if I was starting an app today I wouldn't choose Rails or even Ruby. There are plenty of other options that are almost as expressive and easy to hire for without the speed penalty. If you hire good developers they can get up to speed on any language and any framework. If you don't hire good developers then you're paying a 2x-10x penalty for hiring bad developers and a slower language or framework. Who here hasn't ever worked with or hired a bad developer?

IO is the true bottleneck in most situations but so is a developer writing a view that queries the database for a list of things and then filters them in code instead of letting the database do it. I can't count on two hands the number of times I've seen a developer do this in the past 6 mo.

Your framework and your language are your platform. If you're stuck on a platform, accept it. Rewrites are hard. Hard for the business, hard for your users, hard for your developers. If you're starting from scratch do yourself a favor and pick something that doesn't chop you off at the knees to begin with. Bad code in (Go, elixir, c#, python) is faster than bad code in Ruby.

[edit] english

Some engineers don't want to use ruby, in some cases seeing it as "not a real programming language" (whatever that means)

The performance FUD is probably just deflection.

As DHH himself says, engineers are in short supply - so their preferences tend to get listened to.

I don't know, having to port your app to the next version of rails every year is quite expensive. My golang app however has not needed any porting to the next version for the past 3 years and the syntax and standard libraries are both easy to grasp and rock solid. Oh and the joy of deployment with golang. To each his/her own I guess. Also, if I were to pick a dynamic language, I'd probably go with node.js now.

The article is weird. It is presupposing that there are no other languages that are faster _and_ makes developers as happy as working with Ruby. I count Elixir as one of those.

We converted over an API from Rails to Node (we probably should have just done it in Sinatra but the web application was made in Rails so it made sense) and we went from running it on a 4-core Xeon with 12GB to the second smallest cloud server Rackspace offered. And it was faster.

So you went from one of the largest frameworks in existence written in Ruby to a Javascript runtime built on V8? That might be the least apples to apples comparison I've ever heard. You do realize if you're doing an API you can just use Grape or Sinatra and use like 90% less memory.

Maybe I've missed the meme that Ruby isn't fast enough but I've always found the ability to easily write my tight loops in C and compile it as a Ruby module to make Ruby a go to choice _for_ high performance.

Its hard to think of a scripting language where this isn't an option. But Rails isn't ruby, and loops aren't always the problem.

The fact that just about every rails performance issue ends in another language is the most telling part of the story. IF your php framework is slow, you might see a BIG speed boost from native PHP, or HHVM, or last resort C. Python has a similar option chain, and that just ISNT there for rails.

> Remember: BUT DOES IT SCALE? Basecamp is peaking at 2,000 requests/second against the Rails application instances these days.

Does he mean 2000 rps per instance? If so, that's not bad!

No, he replied ALL instances.... which is... pretty bad.

Shopify listed some numbers below that, too...

I am biased, but I disagree. I've reviewed projects where teams have attempted to compensate for the performance problems of Rails and Ruby by scaling (dramatically) horizontally. Projects that are simple in functionality but have dozens of servers and complex overall application architecture and topology. Projects where the big guns of scalability had to be brought to the battlefield very prematurely.

Today, I argue for quite the opposite approach. Select a high-performance platform that is workable for your team and enjoy the luxury afforded by raising your performance ceiling. Rather than your platform and framework creating an unreasonably low and frustrating performance ceiling—wherein you will find yourself fussing with performance tuning and complex system architecture way earlier than you should, use high-performance infrastructure and defer tuning your application for a long time, if not indefinitely.

Performance is an objective measure, but what performance means to you is potentially subjective. For my part, high performance means peace of mind. I can write my application more quickly, using brute-force algorithms and other quick implementation tactics. I can tune my application later, if and when the need arises.

But if my platform is what causes my performance pain, tuning my application is a futile exercise. I am forced to increase my system's architecture and add more servers, load balancers, messages queues, job workers, all manner of things that make my architecture sound awesome to a programmer but do nothing to improve a user experience where pages are still taking 500ms of server side processing to execute trivial operations.

Yes, with enough effort, essentially any platform and framework could service any application's performance needs. Facebook is famously built on PHP, which is not a fast platform (modest in raw form; slow when encumbered with a framework). Facebook has invested untold scores of dollars into tuning. This is what I feel is important to those of us building just average apps: you probably won't have the money and developer bandwidth to actually tune your platform, as Facebook has done with PHP. So you'll scale horizontally and add a lot of architectural complexity and cost. This might more or less work, and you may be successful in spite of the unnecessary complexity. But my opinion is that it's easier and more comfortable to select for high-performance at the start and just defer that complexity; defer optimization.

I find the upsides of Ruby are subjective. "Programmer happiness" is obviously a subjective matter. I personally am considerably happier on a high-performance platform, especially one that is easy to work with. I am not alone.

Thank you to Ruby and Rails for pushing for a lot of great ideas we enjoy on other platforms today. But its performance has never been good enough for my tastes and that remains the case in 2016.

I've been doing Rails now for over a decade (!) and in some sense I agree with DHH that Ruby is good enough. However I think it's also unavoidable that the Ruby language is designed in such a way that there is a performance ceiling that will be impossible to break through, and that we will increasingly feel that pain of that ceiling as applications get more complex. I still love Ruby, but there is a lot of interesting developments that are catching my eye just as Rails did so many years ago.

It's important to remember what the web development landscape was like in 2004. PHP, Perl, ASP and Java are all weak languages which I would never choose over Ruby. These days things are condierably different. While I have no great love for Node, there are clear benefits to isomorphic client/server code, and going async-first across the board. Similarly whether it's Go, Rust, Elixir, Clojure or Haskell, there is significant community traction in languages that have order-of-magnitude better performance characteristics, and solve problems of both parallelism and type safety which pay huge dividends in performance and maintainability over time.

I still think Rails is hard to beat for rapid prototyping, and I'm not in a rush to jump ship, but I think DHH is kind of sticking his head in the sand here. Once upon a time it made a lot of sense to pay Ruby's performance tax in exchange for the power and expressiveness of the language, these days I think we're seeing the ascendancy of languages that show you can still have great expressiveness while sacrificing much less in terms of performance, parallelism, and safety.

Except that only a small percentage of projects need to scale. So you're generally much better off trading scalability for productivity.

That's precisely the point: a low-performance platform causes you to need to scale and bring out complex system architecture way earlier in your project's lifetime. Systems that would be just fine on a single cheap server using high-performance software find themselves ramping up complexity with only very modest usage.

I'd prefer to avoid the need to scale to deal with a few hundred concurrent users. I'd prefer to imagine my CPU yawning and asking for more.

You may be speaking of very low-traffic systems, and I will agree that with such a scenario, any technology could suffice. But in 2016, we programmers enjoy a lot of options for building web applications and services, including many high-performance platforms that are a joy to work with. Putting aside subjective matters such as existing preferences and experience, if you've got a new project and an open mind, why bother with low-performance when you can have high-performance and ultra-fast response to user requests? To be clear, I'm not saying existing preferences and experience are unimportant. But if you find yourself entertaining the option of using something new, I recommend factoring high-performance into the selection process to enjoy the peace of mind that it brings.

> For my part, high performance means peace of mind. I can write my application more quickly, using brute-force algorithms and other quick implementation tactics. I can tune my application later, if and when the need arises.

This is funny. The only think I like about writing VBA plugins for Excel is that I get to put my algorithms hat on and go for the optimal solution. I remember bringing one implementation from O(n^2) to O(nlgn) and being blown away by how much better the performance was.

Sure, a single server architecture is nice, but for a "real" service you generally end up scaling to multiple servers because you need redundancy. So you end up with that complexity anyways whether you choose a low or high performance framework.

Generally, with a modest application on a high-performance platform, you're going to use X (maybe 2) servers for redundancy purposes only. While this is indeed more complicated than a single server, it's still significantly less complicated than many modest-application architectures I've seen on low-performance platforms. Low-performance platforms tend to find themselves in significantly more complicated architectural territory including sharding work, job queues and workers, clusters of micro-services, a grab-bag of other technologies bolted on in "best fit for the job" fashion, varieties of caching, and so on.

A single load balancer with two identical app servers each of which handle thousands of users is really simple by comparison. You might even have them in cold-failover.

But like I said, what performance means to you is a subjective thing. I personally strongly prefer a high performance ceiling, especially since I can have that while still enjoying a very developer-friendly experience with many modern platforms. There's nothing wrong with big hardware and complex architectures, when you need them, but I'd prefer keeping things simple for modest applications.

My experience is the opposite. All of the rails apps consisted of a single app server that scaled easily, it was the "high-performance" apps that needed the complicated sharding, job queues, message queues, workers, caching servers, et cetera.

All that complicated architecture stuff was driven by business requirements, not by limitations of the platform.

"Fast enough" is a subjective, not objective term. For some things Ruby is fast enough, for other things it isn't. It depends not only on what you are doing with Ruby, but also how you are using Ruby. Just like any other tool.

He said exactly that about three times in his article.

He does but then he immediately hedges it every time by pointing out what he's done with it in the past. As if that were proof that Ruby is fast.

I wanted to state it clearly with no equivocation; fast is relative and Ruby might be fast enough for certain use cases, but not for others.

My Ruby/Sinatra web app is about 2 times faster that my Asp.Net MVC app, so, I always knew the myth of Ruby slowness was that, a myth.

I'd love to hear about the specifics for both of the projects. I have a hard time believing that Ruby is faster than C# straight up, and would venture that such speed differences could be easily contributed to something simple like extraneous queries or what have you.

It was hard to me to believe it too, how is my Ruby/Sinatra app faster than my C#/Asp.Net MVC app? do not compute.

The applications are pretty similar, but request are processed faster with Sinatra, and small queries are no different, you only note the difference when the query returns more tan 100,000 records, but it is an exception to the rule, I suspect it has to do with IIS modules being more heavy than Thin in Ruby.

I was going to say: it almost sounds like something weird with IIS.

The CLR on Windows was/is top-notch. Now, with Kestrel as an option for ASP.NET 5, you're starting to be able to get closer and closer to the metal, so to speak, and eliminate a lot of the baggage required to actually hit your code from an HTTP request.

At any rate, interesting to hear. :)

AFAIK MS are doing and will continue to do the benchmarks for the new ASP.NET and they say that for now it's as fast as Scala/Java but that's not it yet. They plan to make it in top5 stack on benchmarks here[0]. Maybe then people will start believing in C#.

[0] https://www.techempower.com/benchmarks/

I really like Zach Holman's comment on this one.


[0]: https://github.com/holman/ama/issues/698#issuecomment-118547...

I can't remember who said it initially, but my favorite sentiment on all this is:

> The only people still using Ruby are the ones making money.

In other words, I think it's a pretty great, stable community of people who use it in production and have seen it all, so to speak. I kind of include Python in this, too- besides the obvious syntactical similarities, I think they are pretty similar in terms of ideology.

I'm in a bit of my third honeymoon with Ruby (and Rails) this summer. I've been seeing a lot of people in the Go community, for example, talk about "just use the http libraries, no one needs a framework" and I think they're fucking bonkers, or at the very least write backend apps with no UI and no more than two contributors on the project. Frameworks like Rails give you so many security, development, and deployment niceties that I have zero interest in rolling my own anymore. (I saw a "screw frameworks" Go talk that spent ten minutes on how to reload code in development, for example... that was a solved problem for me in 2005.)

I'm kind of in love with the idea of writing everything in Ruby (or something similar) and when it makes sense and can be provably improved, extract it out in something like Go or C. The Go+Ruby combination in particular is super attractive to me, and it's likely going to be fine for the foreseeable future, I think.


[1]: https://github.com/holman/ama/issues/698#issuecomment-118958...

> The recent post from Parse Engineering Team [...] if you look at GitHub also, the number of Ruby repos are getting lower over these months.

I think looking at these examples don't the whole picture here. GitHub, for example, is a fairly feature-complete product, and their next few years will likely focus on optimization work. If you have a mature product, you have a very clear performance profile of what's breaking, what's fast, and what's slow. That's why GitHub, a seven year old company, is more likely to open source Go libraries at this stage of its life rather than Ruby libraries (for example)- it's obvious which use cases can be targeted for speed, maintainability, and shareability.

Parse is another clear example of this- they have a codebase that they've worked with for quite some time, with obvious spots of improvement, so they switched to Go. If you're looking at new companies that need a fair bit of creativity, product development, and development speed, I think Ruby makes a lot of sense. Premature optimization is not just a waste of time, it's an exponential waste of time, as you might head in a wrong product direction that can potentially sink the entire company.

> I am wondering what's will be the next language gonna rule like PHP. Though there are JS tech is in the peak, I still not convinced to use it on server side. Go and Rust looks promising.

I'm really the wrong person to ask here, but I can't really imagine anything taking over like PHP did for the next five years or so. That was a pretty meteoric explosion, and there weren't a lot of clear and open source options fifteen years ago. I don't see JavaScript development being a flash in the pan, I think Go is clearly going to continue to increase in popularity, and I think languages like Ruby and Python and PHP will probably hit a decent cruising speed for the time being. Even .Net technologies have a brighter future ahead of them again. There's a lot of choice right now, there's a lot of resources flooding into open source from companies who clearly want to compete in the community, and there's a ton of stealing of good ideas between communities rather than getting siloed off in the past.

A decade from now, yeah, things may be completely different, but for the time being there's a lot of exciting choices and options happening. Kind of love it.

>"and there weren't a lot of clear and open source options fifteen years ago"

Perl jumps to mind as an example, and PHP stole its lunch money, and ran off.

Ruby is not fast enough for machine learning

If that's your unique concern, then you could still use Ruby and consider using a wrapper for a ML library written in a faster language.

Unless you want to be writing ML algorithms yourself.

If that's not the case, maybe you will find this interesting: "TensorFlow is coming to Ruby" - http://www.somatic.io/blog/tensorflow-is-coming-to-ruby

Yes, most people are aware of that, and so they don't use Ruby for machine learning.

This argument holds water until you have languages that are orders of magnitude faster with the same developer enjoyment and experience. 13 years ago, I'd argue that choices were rather limited. Nowadays, there are too many choices. Fast enough is just not good enough in a market with plenty of competition.

What is fast enough? If you're building a web app, fast enough is not the same as if you're building a web API. The latter needs to perform much better than the former in my experience because the former might make multiple calls to the latter in a single request. I find it almost impossible to make an argument for interpreted languages at this point for backend services considering how slow they are and how few, if any, benefits they have over the many non-interpreted languages out there. I'm thinking of languages like Clojure and Elixir, but even Java has a framework that supports hot code reloading (Play) thus getting rid of the last remaining benefit of an interpreted language. Once you get rid of that, it really no longer makes sense to use an interpreted language, all other things that DHH mentioned being more or less equal.

"Orders of magnitude faster" isn't possible in any case where more than 10% of your time is spent waitin on external factors (kernel space, waiting on IO etc.), which is the case for pretty much everything I've ever done.

There are certainly types of code that will be CPU bound, in which case, yeah, there's a good case for using something else - or calling out to something else -, but for large parts of what people write, not being IO bound is a warning sign that you should take a long hard look at what you're doing, because chances are you're doing something silly.

Webapps and typical APIs for webapps tends to be amongst those.

Of the work I've done in the last 20 years, maybe 2-3 projects have been projects where CPU performance have been an issue. For others it will be every project they every do. But the point is there are plenty of us for whom language performance is not a factor we usually need consider.

I benchmark most interpreted language http frameworks in the low tens to hundreds of requests per minute range at best without any app code and you're telling me that CPU performance isn't an issue?

No, I'm telling you that CPU performance usually isn't an issue. Most sites will never, ever need to serve enough dynamic requests for that kind of performance to be an issue (and you can certainly do far better than that on dirt cheap hardware).

> with the same developer enjoyment and experience

Expand on this please?

DHH is ridiculous. Ruby and Rails are nowhere near fast, in the past or present. Especially the past.


> The main Rails application that DHH created required restarting ~400 times/day. That’s a production application that can’t stay up for more than 4 minutes on average.

I don't know enough about Ruby/Rails specifically to have an opinion on whether it's a correct argument, but:

Ruby and Rails are nowhere near fast

Is not what's being argued. What's being argued is that "not fast" and "fast enough" are not mutually exclusive. My experience with other "slow" languages (primarily Python) is that this is true; even when the language implementation, or the application stack on top of it, is objectively "slow" compared to a similar stack in another language, often it simply makes no difference because that "slowness" gets lost in the noise of all the other, much slower, things a web application has to do.

I'm reminded of a wonderful blog post from years and years ago that I unfortunately can't find, which showed a pie chart of realistic profiling data from an application -- majority of time spent in things like network I/O, talking to its database, etc. -- and had a tiny tiny little slice labeled "Template rendering". It then pointed out that according to many people (fights among Python templating systems were common then) that was the obvious place that needed to be optimized for performance, ignoring everything else in the pie chart.

Your link doesn't say it's wrong; it argues semantics. The fact that unicorn-killer is a real thing real developers use for real apps should be evidence enough that Rails is a joke. Whether your app crashes after 4 minutes or you kill it after 4 minutes is irrelevant.

> The main Rails application that DHH created required restarting ~400 times/day. That’s a production application that can’t stay up for more than 4 minutes on average.

That isn't a complaint about performance.

Curious: what is your definition of performance and how do you view this complaint?

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact