Live data from Hacker News

Ruby 3.3's YJIT Runs Shopify's Production Code 15% Faster

railsatscale.com

151–158 of 158 posts

Re: Ruby 3.3's YJIT Runs Shopify's Production Code 15% Faster

#151
post #139

I'm probably misinterpreting the numbers, but it sounds like the 3.3 interpreter also got some significant performance improvements - if 3.3 YJIT got a 13% speedup compared to 3.2 YJIT and a 15% speedup compared to 3.3 interpreter, that sounds like the 3.2 YJIT has only slightly better performance than the 3.3 interpreter. Is that interpretation correct? If so, what were the improvements in the 3.3 interpreter, or wa…

That is exactly my question as well. Why would I want YJIT if it is only 15% faster than normal Ruby? Given the memory overhead.

The 15% is for the total request time including waiting for blocked IO.

> All that work allowed us to speedup our storefront total web request time by 10% on average, which is including all the time the web server is blocked on IO, for example, waiting for data from the DB, which YJIT obviously can't make any faster.

https://twitter.com/paracycle/status/1605706245955997697

Re: Ruby 3.3's YJIT Runs Shopify's Production Code 15% Faster

#152
post #129
post #126

Earlier quoted context omitted.

> serious learning. That's another problem I have in this narrative. Productivity isn't measured by throwing an inexperienced developer at something and then looking how fast they get stuff done. That's learnability. I'm an experienced Rails developer (some 15 years in) and my productivity has plataued for years now. I've been doing Java and Rust work for years too now. Web and application dev. It took years, but my…

We're talking past each other because we're arguing different things. If I understand you, you're saying that you can avoid technical debt by using tools that are intrinsically more performant, and that skilled developers are more productive with more advanced tooling. That's all correct. But the point I'm making is that if an MVP isn't accruing technical debt, it's over-engineered. Most of them will be thrown away,…

I agree entirely about that tech debt. I've built, sold, grew and failed several startups myself. Many with Rails at the center. I've been building with Rails for way over a decade, so I'm well aware of the "options" back in the day.

What I'm arguing, however, isn't to take on debt¹, I'm saying that productivity and performance aren't always opposites.

Sure, Rails trades in performance for productivity. But, I've learned, this is mostly just Rails. There are many languages and frameworks that are just as productive (for a certain definition, see previous comment) as Rails, but also performant. And I'm arguing that performance affects productivity: a performant, scalable software is easier to work on, because it gives faster feedback (tests, ci, manual testing), wastes less time waiting for stuff (hundreds of single seconds add up over days and weeks weeks), and decreases friction (I'll postpone running the full test suite if I know it'll hog my machine for the next half hour. I'll gladly run it, if it takes a few minutes or less).

Edit: and, if what you say about tech debt is true (I think it is), wouldn't Shopify be at a position now to pay it back? Many startups that used Rails paid it back by migrating elsewhere. So maybe Rails in its entirety is Tech Debt?

¹A cautionary sidenote, that I've learned the hard way, is that taking on tech debt is an art in itself. Not all debt is alike. Many kinds will cripple my project. Where at the unlikely moment that I do need to scale, that's impossible. Or when I do need to pivot for the umpteenth time, we cannot, without that Giant Refactoring.

Re: Ruby 3.3's YJIT Runs Shopify's Production Code 15% Faster

#153
post #101

Earlier quoted context omitted.

Not in my case. Rust, for me, is much better for productivity than my other major languages Ruby and JavaScript. The main reason is type enforcement, which is why -for me- typescript is much more productive than JavaScript. A large category of bugs simply won't exist (are caught at compiletime). With Ruby, I'd have to write hundreds of edge-case unit-tests just to cover stuff that, with Rust is enforced compile-time…

I like strong typing as well, and worked with a strongly typed language for years before Ruby. Then I did Ruby+Rails fulltime for 9 years. Just recently moved on. With Ruby, I'd have to write hundreds of edge-case unit-tests just to cover stuff that, with Rust is enforced compile-time for me. Never a problem for me. It was one of my major concerns about Ruby, prior to starting out. But like... it just wasn't a proble…

> # you would have to be a psychopath to pass this > # anything but a User object > def grant_admin_privileges(user:)

I had an app once where we used user objects, and later switched to ids to save db calls. Now you have some functions that can accept both, and some that accept one of them, and without type hints (that was long time ago) you can easily make a mistake.

Re: Ruby 3.3's YJIT Runs Shopify's Production Code 15% Faster

#154
post #86

Earlier quoted context omitted.

Is TruffleRuby compitable with Rails? If so, I wonder how much TruffleRuby would improve the performance and memory footprint. Especially with native images, I wonder how that would turn out.

> Is TruffleRuby compitable with Rails? Rails proper, yes. Small rails app are generally drop-in compatible, but sizeable applications are likely to run in a few compatibility issues as most gems aren't tested against TruffleRuby. > I wonder how much TruffleRuby would improve the performance and memory footprint. The generally speaking Truffle is much faster at "peak" performance, but take very long to get there whic…

Thank you for the informative reply.

Ruby atm is working towards implementing true parallell execution with Ractors for example, and now with YJIT, the performance might increase some more.

Re: Ruby 3.3's YJIT Runs Shopify's Production Code 15% Faster

#155

Earlier quoted context omitted.

I like strong typing as well, and worked with a strongly typed language for years before Ruby. Then I did Ruby+Rails fulltime for 9 years. Just recently moved on. With Ruby, I'd have to write hundreds of edge-case unit-tests just to cover stuff that, with Rust is enforced compile-time for me. Never a problem for me. It was one of my major concerns about Ruby, prior to starting out. But like... it just wasn't a proble…

> # you would have to be a psychopath to pass this > # anything but a User object > def grant_admin_privileges(user:) I had an app once where we used user objects, and later switched to ids to save db calls. Now you have some functions that can accept both, and some that accept one of them, and without type hints (that was long time ago) you can easily make a mistake.

That sounds like some malpractice.

Ruby has had keyword arguments since Ruby 2.0 from 2008 and earlier code could certainly use option hashes.

So I don't see a reason for any confusion there.

    # probably malpractice in a system where many methods
    # take IDs and some take Users
    def do_something_with_user(user)
    end

    # how hard is this? trivially easy and unambiguous.
    def do_something_with_user(user_id:)
    end
In the second example, you would really have to be asleep at the wheel to make a mistake like:

    # this is obviously wrong
    do_something_with_user(user_id: User.first)
I don't see the problem. It would be nice if a compiler/IDE could catch that, but on the other hand, it just looks blatantly wrong as you type it and will certainly blow up the first time you call it.

Re: Ruby 3.3's YJIT Runs Shopify's Production Code 15% Faster

#157
post #149

Earlier quoted context omitted.

Locked under company copyright, and not shareable, of course.

Pity, the world is prived from such wonder.

Well, something tells me that someone "mostly busy with Java, C#, and JS/TS" is going to be a tough sell anyway.

Re: Ruby 3.3's YJIT Runs Shopify's Production Code 15% Faster

#158
post #127

Earlier quoted context omitted.

I dare you to have a look at your rollbar, sentry or other exception logging of a rails project. And I'll put money on it, that the top 5 exceptions has several 'undefined method x' (probably on nil) errors. Those warrant unit tests. Those will regress. Those would never exist in a strongly typed language (though Java still has null...ugh)

Yeah that's the usual argument and I don't agree. It's true that 99.9% of production log errors are NoMethodError exceptions. annnnnd 99.9% of those NoMethodErrors are just code not handling nils/nulls correctly annnnnd 99.9% of those unhandled runtime nils/nulls are from external data (user inputs, database data, etc) So strong typing doesn't help you there at runtime, it just blows up differently.

> So strong typing doesn't help you there at runtime, it just blows up differently.

It really does, though. Not with the Java-type of strong typing (still allows null) but with the Rust type of strong typing. Simply because it moves all this to the edge. At the point where you read the CSV/database/HTTP-response/user-input.

Everything inside of this edge (a strong boundary) doesn't need to to deal with "can this be nil" because it can't. Your `the_outlier(items: Vec)` will simply not compile if the type-checker sees that `items` can be nil, `items` can contain a nil, or, internal to that function an items[].measured_at might be nil, or maybe items[].measured_at is a Date instead of a DateTime.

You don't need a bazillion tests to deal with this situation around `the_outlier()`. That doesn't mean that the part that reads a Vec from a CSV (or json, or database or whatever) is covered by this typechecker. But it means this layer, the edge, the boundary, is where you put the protection. Validation, whatnot.

Post reply on HN