Hacker News new | ask | show | jobs
by sbov 2584 days ago
> Great for CPU-intensive tasks.

Ruby is among the slowest languages out there. Which is fine for most webapps, but calling it great for CPU intensive tasks... I don't understand what logic is being used to come to this conclusion.

3 comments

Rails is slow. Ruby isn’t slow.

Ruby has the same thing that every other language has, call outs to C code under the hood for most of the real work.

What makes Rails slow is the process around so much object creation and destruction, but this is exclusive to Rails itself.

You put a Sidekiq worker up against a Go worker for some background processing and the performance is comparable.

> Ruby has the same thing that every other language has, call outs to C code under the hood for most of the real work.

Yes, this is exactly the problem. Ruby is so slow that you end up writing C extensions when you want to do any non-trivial computation. The documentation is bad, the tooling is bad, the build/CI complications are bad, and there's not much community info online about the process. And now your RoR developers have to support a C library, where a segfault can kill an entire Ruby interpreter.

I don't think most RoR apps run into these problems, which is why RoR is such a great thing in the first place, but we shouldn't brush aside how slow it is, and the implications of that when it becomes a problem.

> Ruby is so slow that you end up writing C extensions when you want to do any non-trivial computation. The documentation is bad, the tooling is bad, the build/CI complications are bad, and there's not much community info online about the process.

Perhaps for a classic C extension that's true, but (for portability across Ruby interpreters and other reasons), using FFI is usually the preferred way to do new C interop, and none of that is true for FFI.

Don’t get me wrong, there are faster languages out there.

The trade off that Ruby has always made was maximizing developer productivity. It’s never tried to be the fastest, but it’s plenty fast enough.

> And now your RoR developers have to support a C library

In Python you can write your low level extensions directly in Rust via PyO3 [0]. I guess there is something similar for Ruby.

[0]: https://github.com/PyO3/PyO3

When Rails came out, Ruby was the slowest language by far because its interpreter literally just walked an AST. No intermediate byte code, no VM, it just eval'd an AST. This reputation stuck longer though, although yeah I imagine Ruby is still slower than Python and Node even now despite having a VM.
Current stable version Ruby 2.6.2 with --jit is actually faster than Python 3 according to this: https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
And actually slower also.
When the JIT really gets rolling mainstream, it could help quite a bit. Performance (3x over v2) is a primary goal of Ruby 3.

https://developers.redhat.com/blog/2018/03/22/ruby-3x3-perfo...

Ruby _is_ itself slow by any meaningful metric. That being said, the productivity gains usually outweigh the slowness.

I've been doing Elixir/Phoenix lately and subjectively it feels significantly faster than Ruby/Rails.

When I get half a million users I’ll start worrying about it. Most startups fold way beyond this point. Saving dev time and the pleasure and ease of working with Ruby more than make up for the speed difference.
It will scale well beyond that point if ut is properly organized into services.

Check out some of the comments above about "service oriented monolith".

That being said, know your limits. If you are doing a lot of image processing for instance it may be worth investing in an external service in a language that is a better fit for that problem.

I think it's only in comparision to php, python etc.
Ruby 3x3 is a thing (make Ruby 3.0, 3x faster), and Ruby 2.6 is said to include an optional JIT compilation mode.

I haven't seen any benchmarks or analysis that say JIT is ready for production use, but indications are strong that the next version of Ruby will include a lot of surprising things, like maybe a type system?

Ruby got a reputation for being slow very early on, and my understanding is a lot of that was due to slow code in Rails (version 2 and/or 3?). Rails is a lot better now. Ruby continues to evolve. Still, I don't know how many Ruby developers have chosen it for reasons owing to CPU-intensive work. This does seem like a stretch, even if we are beating Python in some benchmarks.

> Ruby 2.6 is said to include an optional JIT compilation mode

You make it sound like an unconfirmed rumour? It's there in the release.

With the amount of object allocation in standard Rails behavior, it seems to currently perform worse in most applications. But it's a stepping stone for the future. Basically, it's there - but few/no people are using it.
Yes the key thing the Ruby JIT needs to eventually do is reduce the load on memory allocation and the GC - that's where the benefits will be in the future.
Yes, it's there, you can enable it, but I haven't heard anyone recommend it for production use, and it's not enabled by default. I tested it myself, it seemed to make my boring use case a little bit faster, once the JIT cache is initialized.
> it seemed to make my boring use case a little bit faster

That's an unusual result - if it's faster for an actual app you're using in production you should report that as they'll be thrilled.

If you can call it that... my site is actually a Jekyll blog, in development mode, this is running in the most needlessly Ruby way. (A production deployment would have pre-rendered all the pages, and there wouldn't be a need to have a Ruby process even be present on the running server.)

Each visitor hits a Ruby process which renders the page directly, or serves it up from filesystem cache. I'm not honestly sure which, it could be monitoring the filesystem for changes to the markdown files, and only recompiling them when it observes a change on disk... or it could be rendering each request freshly for the visitor.

It would be hard-pressed to call this a production deployment though, I can say without a blog post or any hard data to back it up that when I did side-by-side trials, the page loading response times were marginally faster with the JIT enabled, after repeated trials.

After watching @tenderlove's talk from RailsConf 2019, I think I'm obligated to say also about this that, your results will improve if you paid attention to cache hit ratios, and consider tuning the JIT Cache size to achieve the maximum benefit. Perhaps these things will be better in a later iteration of Ruby JIT?

I was listening to a recent interview with DHH and he makes a great point that Rails and Ruby are about optimizing for developer happiness and dev speed. Computing power keeps becoming cheaper and ruby keeps getting faster but developer's salaries continue to be the number one cost for software companies.
It's not so easy.

Computing power can be increased by scaling vertically or horizontally. Vertical scaling has an upper limit, and when one reaches it, in certain contexts, end of the happiness :-)

Case in point: GitLab; they have Go microservices. GitHub was also hiring Go developers, so very likely they've done the same.

Of course, few companies are GitLab/GitHub, but the point is that it's not possible to make absolute statements about power being cheap.

Agreed. Yet even if you don’t reach Gitlab scale, languages like Go and Elixir can help you deliver the same service at 10-20% the cost.

By being able to run your service on a single server instead of ten allows your team to focus on features instead of scaling your application using background concurrency, caching, or “micro-services”.

Imagine what you could do when you don’t need to manage a fleet of web-servers.

100% agree. Developer happiness, conceptual compression is another important concept that DHH likes to talk about. If there's a hard topic that devs need to understand sometimes, Rails makes it a point to guarantee that devs don't need to understand all those things all the time.

Conceptual compression means that you can unpack those ideas and work with them when you need them, or pack them back up and don't pay attention to them when you don't need them.

The biggest example that I can think of is ActiveRecord. I can't tell you the number of times I've seen presentations by programmers who work with other frameworks like .NET, who have embedded large, complex SQL queries into their code. They don't think twice about it, don't even flinch, parsing SQL is part of the cost of doing business in this language.

Just a disclaimer, I work with Rails every day, but I don't really like it all that much and I really don't like ActiveRecord. We have Rails legacy apps and I maintain one of them. I'd still use Rails for some things, but it I'm pretty picky about what I think it's good for.

Having said that, it makes me a bit sad that there are quite a few developers who actively avoid SQL. Granted the syntax is absolutely awful, but it is a very useful and powerful language. The concepts behind relational databases are embraced by SQL in ways that I can't imagine in any other language (I'm sure there must be other good relational query languages somewhere, but I've never been exposed to them). Honestly, if I have developers working with a relational DB doing anything even a little bit complex I want them to not not think twice or even flinch to use or read it (and I say that not really being all that accomplished with the language myself).

Rails has some good niches where it is very well suited. ActiveRecord is OK if you have a very particular data model. However, as they say, if a hammer is your only tool, every problem starts to look like a nail. You may find that if you approach the problem differently, you will find reasons why people choose not to use very simplified ORMs.

As a counterpoint, I love ActiveRecord. It's a Swiss Army knife that's got pretty much everything you need, you just need to find the right tool and use it.

What ActiveRecord isn't is discoverable. Which is to an extent understandable. Its domain is literally anything you could express in SQL. But you really can do anything you want with it, you just have to find the right abstraction. A tool I use a lot is to .to_sql which will show you the compiled SQL fragment in a debugging session. You can compose with bare SQL fragments and ActiveRecord even includes an intermediate library so that you can work at the relational algebra level if you want.

It's not that ActiveRecord forces you to work a certain way. It just doesn't advertise all its features.

I agree! SQL-avoidant developers are something we actively try to screen out in our interviews. (Being too gung-ho about using raw SQL -- something I've been accused of --is bad too, but at least it's not a path of willful ignorance)

    Granted [SQL's] syntax is absolutely awful, but 
    it is a very useful and powerful language. The 
    concepts behind relational databases are embraced 
    by SQL in ways that I can't imagine in any other 
    language (I'm sure there must be other good relational 
    query languages somewhere, but I've never been exposed 
    to them)
Is SQL's syntax really that awful? I think any language that maps fairly closely to relational algebra will wind up looking similar, and a lot of frustration that we feel toward SQL's syntax is because sometimes we want to express procedural concepts in a language that is based on relational algebra.

It's somewhat significant, I think, that when Microsoft came up with LINQ (sort of a language- and backend- agnostic query language) they basically settled on something that looks like SQL but puts the FROM clause first, mainly so the editor can give you typing hints.

I'm not saying LINQ was a rousing success, but that was a pretty major greenfield MS devtools initiative and they have some pretty smart language/compiler people, so it's interesting that they settled on something not too different from good ol' SQL.

Python3+ and PHP7+ are faster than Ruby though. Maybe they were comparing modern ruby to 10 year old PHP/Python?
Faster based on what benchmark?
In all of those benchmarks ruby runs with —jit
And … ?