Live data from Hacker News

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

railsatscale.com

11–20 of 158 posts

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

#11
post #8
post #5

Earlier quoted context omitted.

This is a particularly valid concern given ruby+rails seems quite memory inefficient to begin with. I've sometimes had smallish apps on 500mb heroku dynos crashing due to memory slowly climbing and eventually slowing things down as the dyno uses swap, and eventually 500mb of swap. IME ruby+rails doesn't seem to free up memory after it uses it, and that causes problems as the hours go by until the pod/dyno crashes or…

I’ve observed same, and every time I switched to jemalloc and the issue was fixed.

Was it difficult to switch? What were the downsides / tradeoffs? (I read about jemalloc recently but don't know enough about it to confidently pursue it, but may try it on a small app if it's straight forward).

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

#12
post #11
post #8

Earlier quoted context omitted.

I’ve observed same, and every time I switched to jemalloc and the issue was fixed.

Was it difficult to switch? What were the downsides / tradeoffs? (I read about jemalloc recently but don't know enough about it to confidently pursue it, but may try it on a small app if it's straight forward).

Super easy and have not had an issue with it in over 10 years of using it. There is an example here on how to do it with docker image. https://mailsnag.com/blog/optimized-ruby-dockerfile/.

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

#13
post #2

> 1.27 million requests per second > 3TB/minute of traffic "rails doesn't scale"

Rails scales fine. People use that as an escape hatch when they don't know how to write performant code.

You don't even have to write performant code. You can just start as many instances of the rails app as you want. The bottleneck is usually the database.

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

#14
post #10
post #2

> 1.27 million requests per second > 3TB/minute of traffic "rails doesn't scale"

That's not on a per-host basis. Shopify's design is, quite fortunately, one that partitions really well, as each store is completely independent of each other. Each store can be assigned to one pod, each pod can have as many hosts as it takes to optimize the use of a database instance, and then you can add more pods as the need arises. Edit: to be clear, that's not to say Rails can't scale. It can. It's just that it…

Sure.. but isn't that a database problem and not a rails problem?

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

#15
post #9
post #2

> 1.27 million requests per second > 3TB/minute of traffic "rails doesn't scale"

These two points are entirely unrelated. Scaleability in that meme is not considering horizontal scalability, which approaches infinity for literally any language/framework. It only makes sense in the context of vertical scalability, and gross req/sec offers no insight into whether or not that's true.

I can't see how vertical scalability even matters for rails You can just start more instances. It's not like two active web requests need to interact with each other.

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

#16
post #10

Earlier quoted context omitted.

That's not on a per-host basis. Shopify's design is, quite fortunately, one that partitions really well, as each store is completely independent of each other. Each store can be assigned to one pod, each pod can have as many hosts as it takes to optimize the use of a database instance, and then you can add more pods as the need arises. Edit: to be clear, that's not to say Rails can't scale. It can. It's just that it…

Sure.. but isn't that a database problem and not a rails problem?

No, they both matter. The database can handle X shops per partition, and the rails host can handle Y shops per partition.

If rails were half as fast, you'd need twice as many rails hosts (but no more databases).

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

#17
post #12
post #11

Earlier quoted context omitted.

Was it difficult to switch? What were the downsides / tradeoffs? (I read about jemalloc recently but don't know enough about it to confidently pursue it, but may try it on a small app if it's straight forward).

Super easy and have not had an issue with it in over 10 years of using it. There is an example here on how to do it with docker image. https://mailsnag.com/blog/optimized-ruby-dockerfile/ .

Going to try this right now! Will report back.

OOC, why isn't this part a ruby default? Isn't it always better to be more memory efficient. (I'm trying to understand what the trade offs are, if any)

EDIT: well, exactly 6 minutes later, I'm done. I followed these instructions: https://elements.heroku.com/buildpacks/gaffneyc/heroku-build...

The app seems to work like usual, I'll just have to wait and see what happens to memory use.

I will reply here in 12 hours with a screen shot showing the results (before/after memory use), whatever they may be.

Also, for reference, here's the metrics for the past 24 hours (LOTS of memory problems): https://imgur.com/a/M8IHd5z

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

#20
post #5
post #3

15% faster is great. But at what cost? > Since Ruby 3.3.0-preview2 YJIT generates more code than Ruby 3.2.2 YJIT, this can result in YJIT having a higher memory overlead. We put a lot of effort into making metadata more space-efficient, but it still uses more memory than Ruby 3.2.2 YJIT. I'm hoping/assuming the increased memory usage is trivial compared to the cpu-efficiency gains, but it would be nice to see some me…

This is a particularly valid concern given ruby+rails seems quite memory inefficient to begin with. I've sometimes had smallish apps on 500mb heroku dynos crashing due to memory slowly climbing and eventually slowing things down as the dyno uses swap, and eventually 500mb of swap. IME ruby+rails doesn't seem to free up memory after it uses it, and that causes problems as the hours go by until the pod/dyno crashes or…

Ruby processes don't return the memory to the system,they reuse memory already allocated. This is for efficiency - allocating and freeing system memory isn't free. Even if it did, your peak memory usage would be the same. It doesn't allocate memory it doesn't need.

If your memory usage doesn't plateau you have a memory leak which would be caused by a bug in your code or a dependency.

But 500 to 1gb of memory required for a production rails app isn't unusual. Heroku knows this, which explains their bonkers pricing for 2gb of memory. They know where to stick the knife.

Post reply on HN