Hacker News new | ask | show | jobs
by benkuhn 2230 days ago
Really surprised how many commenters are talking about using a faster language when the example of slow code in the post is failing to cache the results of an expensive database query.

In my experience, even in "slow" languages, that type of thing is the predominant source of major performance problems, and the supposedly "slow" language would be perfectly adequate if you an stop shooting yourself in the foot (and if you can't, a faster language will not help you).

I'm sure there are extremely high-performance or high-scale points where language choice starts to matter more, but I'm also not surprised if Shopify is correct not to think they're there yet.

3 comments

Most CPU intensive functionality in the core Ruby lib is implemented in C anyway, to ensure performance.

The vast majority of overhead in the rails app I work on is poorly build data models and poorly written queries. It makes no sense to talk about marginal gains of a few percent or a few ms per request when there are DB queries that take multiple seconds to complete.

In our case, a large part of that is due to the decision that someone made 5 or 6 years ago to store large amounts of data as serialized ruby hashes in the DB, rather than JSON (unsure if postgres supported it at the time), or simply as separate tables.

None of the poor performance of our codebase is down to Ruby itself. Most of it is due to features and data models being implemented with no thought for performance, a lot of which wasn't an issue when first written but as we've grown have become a constant thorn in our side (e.g. retrieving a multiple-MB serialized hash from the DB just to grab 3 values, then doing this 10 times in a request)

Interesting, how are you guys thinking of solving this issue? I'd go for cache or just migrate the table to a different structure I guess
It is surprising until you realize that Rails' ActiveRecord consistently wastes 100-200ms on every request just to serialize / deserialize data from/to the database.

So yes, a language that's both faster and has less overhead in its ORM / DataMapper library definitely will help you.

Our data-heavy API returns JSON responses from our DB in ~40ms using ActiveRecord. So no, it doesn't waste 100ms on every request! We're serving around 6000 requests like that per second.
Well, you likely have a dedicated (or pretty strong) server.

The Heroku dynos I've tested with some years ago performed quite horribly. Only a proper Xeon server was able to achieve sub-100ms responses.

But hey, if Ruby improved in the meantime, cool.

Rails on Heroku is about the most inefficient combination you can get for a web server.

I've always thought of it as the platform you use for running toy apps with maybe a couple of dozen users at most and a low load. It's incredibly quick and easy to get a Rails app running on Heroku, a couple of hours at most. But you pay (in dollars and performance) for this.

You'd be surprised. I know companies paying $2000+ a month for Heroku and are still having performance problems with Rails.

(Then again, they have them with Phoenix as well but to a lesser extent.)

Yeah, Heroku performance on shared dynos is really not great. The variability is very high also, so you'll get some requests seemingly randomly timing out. The dedicated performance dynos are better, but even more expensive. We were on Heroku for a long time but as the scale got too much we migrated to Google Kubernetes Engine which has been great.
That's not remotely true. If this is happening to you then you're almost certainly having N+1 problems which is architectural and would affect any solution you're using. Add google trace to get a breakdown of your requests SQL that's executing.

In an unusual situation it is possible in PG to have a very large pg catalog if you have thousands of tables and schemas which is resolved at run-time because Rails resolves models and types through db introspection, and the types specicially are only loaded during runtime. But that would be very unusual. I'm working on solving this in Rails because this unusual sittuation is affecting us.

I can only presume things have improved in the meantime.

Still, I regularly chat with Rails devs and to have a MacBook Pro 2018 return responses in 150+ ms is alarming. But you might be right that it could be a N+1 query problem.

Even without those though, I've still seen Rails apps perform quite horribly. So 50/50 from me, you might be correct but I wouldn't entirely discount the option that Rails is still quite suboptimal in terms of performance, compared to many other frameworks.

I mean I see rails perform horribly too, it's my job to go in and fix things, and I focus a lot on fundamentals (what's your DB doing, what data do you need to serve the request, what shouldn't be inside of the request-response cycle).

Because a lot of web developers these days build applications and ORM's are great but make certain patterns convenient so it's really easy to code yourself into places that don't scale. Then people reach for various caching solutions rather than taking a step back and looking at what's actually executing.

I've seen just about every bad pattern you can imagine and it's not usually obvious because the code looks simple enough. Like that permission check in your controller is actually serializing 1000 ids and querying against them, or that .first doesn't have an index so you're sorting the whole table, and much worse than that.

Sure. This is a thing regardless of language and framework. Point is, there exist some of them that are quite forgiving and don't give you a 150+ ms response time out of the box like Rails does for a number of projects I inherited in the past.
ActiveRecord is configurable. You have options to bypass the serializer. Rails can't magically have the correct answer to every problem out of the box without tweaking

"The default behavior is slow!"

"Don't use the default behavior?"

But if you are going to override the defaults, then the argument of "Rails is performant out of the box" no longer holds water, does it?
Was that an argument? It seems pretty clear that that is not the goal of Rails. I'm arguing here that "Rails can't be performant" is not necessarily true
Sadly often this is the argument, yes.

I am glad to see that there are much more reasonable Rails devs out there compared to some rather toxic individuals around in HN at least!

A lot of tech can be fine-tuned to be very performant. My point was (still is) that there exist technologies today that allow you to delay your scaling decisions much further in future, compared to what a stock Rails app (without any performance tuning) will.

+1 I definitely agree with this. Today there are many strong languages/frameworks that are just as productive or close to as productive as Rails, particularly with more modern languages. I was really impressed by Phoenix when I worked with that. It was very easy to scale out when the time came because of all the support OTP gave you and because of design decisions like immutability by default
Most languages bring their own ecosystem and associated phosphophy of how you'll use it.

The Ruby phosphophy seems to be lots of magic (in a good way) and in exchange you accept that details get lost behind the scenes and that it's only fast enough, but not truly fast.

Switching to a language that values speed with tools that have a different phosphophy can then make such a bug much more visible, due to the lack of behind the scenes magic.

While the phrasing irks me, I think I agree with the sentiment: "languages that value speed tend to expose more of the details, thus when presented with a performance problem, you have more options ready at your disposable". One of the biggest barriers for me personally as a long time user of high-level languages is going down into C internals and feeling like I can safely make changes. It also sucks if you don't want something that comes out of the box with Ruby (say you want a more memory efficient array than what Ruby gives you). C extensions allow you to add these things, but the knowledge is specialized and writing C extensions can feel like a black art due to a relative lack of resources on them

There are two other alternative interpretations that I think are untrue however:

* "languages that value speed give you tools that expose more of the details and thus help you avoid adding defects in the first place" which I disagree with because (1) the average programmer will not understand what most low-level options actually do and (2) exposing more options is like trying to program with ones and zeros - at some point low-level abstractions don't scale well in a constantly evolving project

* "languages that value speed generally have fewer abstractions and thus make it easier to find bugs because there is less abstraction" which I think is untrue in projects of meaningful size. Macros are very common to find in languages like C and arguably as complex as metaprogramming in Ruby. Additionally Java is considered a relatively fast language and Java projects often have lots of abstraction