Live data from Hacker News

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

railsatscale.com

111–120 of 158 posts

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

#111
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 was 3.2 YJIT just not much of a speedup?

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

#112
post #48

Earlier quoted context omitted.

> 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. Extremely bold claim for a framework the size of ruby on rails. I would trot out my own evidence but the receipts are lost with time. Also—why isn't the allocation behavior tweakable at runtime? Seems pretty trivial with no downsides. It's not difficult to think of a scenario where a non-monotoni…

This person is incorrect, but even if they were correct, that wouldn't be a framework thing. Memory management is handled by the language.

Many types of memory leaks are simply because you're holding on to data you don't need to hold onto anymore. Languages cannot prevent this, at least not that I've seen.

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

#113
post #48

Earlier quoted context omitted.

This person is incorrect, but even if they were correct, that wouldn't be a framework thing. Memory management is handled by the language.

Many types of memory leaks are simply because you're holding on to data you don't need to hold onto anymore. Languages cannot prevent this, at least not that I've seen.

Sure, but the person I responded to was suggesting that Rails was deliberately holding onto memory to re-use it.

That's absolutely not something Rails does, but it is something that some managed languages and some (most?) allocators do.

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

#115

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…

> Overall YJIT is 61.1% faster than interpreted CRuby! > On Railsbench specifically, YJIT is 68.7% faster than CRuby!

https://speed.yjit.org/

For 3.2 there also was an improvement of the interpreter:

> We now speed up railsbench by about 38% over the interpreter, but this is on top of the Ruby 3.2 interpreter, which is already faster than the interpreter from Ruby 3.1. According to the numbers gathered by Takashi, the cumulative improvement makes YJIT 57% faster than the Ruby 3.1.3 interpreter.

https://shopify.engineering/ruby-yjit-is-production-ready

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

#117

Earlier quoted context omitted.

What if the other thing you're trying to run runs at the same time that your rails app is using peak memory? You have no choice but to have enough memory for peak load. But if you really do need to cheap out you can generally configure your app server to kill idle worker processes, or bounce them on a schedule to return memory to the system, and hope.

So that’s generally not very likely. You’re going to have some time of day effects that are shared but true “peak” tends to be service dependent rather than something all your services experience simultaneously from what I’ve seen (YMMV). Killing “idle” processes is also extremely expensive because you have to restart the process, reload all state, and doing graceful handoff is tricky. It’s good to have graceful hand…

There is no one size fits all memory management technique. There are always tradeoffs. The scenario you are describing is not common for ruby apps. Ruby uses a memory management style that is suitable for most ruby workloads.

All the production quality app servers handle killing and and starting new worker processes gracefully and efficiently by forking a running process. Certainly there is some overhead, but that's why you don't underprovision memory, so you don't need to resort to that.

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

#118

Earlier quoted context omitted.

Theoretically virtual memory and swap solve this problem really well. The OS is free to write the unused pages to disc to let other programs use the real memory.

Swap is horribly expensive and most hyperscalars run their servers without swap and set per-process memory limits, automatically killing workloads that go above their threshold..

swap is only expensive if you are using the swapped out memory. if you are in a case where a program is just holding on to pages it isn't using, swap is basically free. for most users, turning off swap is just losing performance since the OS can always use all of your RAM to cache disk access.

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

#119
post #47

Earlier quoted context omitted.

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…

> Ruby processes don't return the memory to the system That is not correct. Ruby do unmap pages when it has too many free pages, and it obviously call `free` on memory it allocated once it doesn't use it. What happens sometime though is that because of fragmentation you have many free slots but no free whole pages. That is one of the reason why GC compaction was implemented, but it's not enabled by default. But in mo…

I'm correct in practice. There are scenarios where ruby might free memory, but ruby is mostly used for rails, and you won't ever see that under a standard rails workload. It will plataue and stay there until a restart. When people see this they think it's a "bug" or a "leak" but it isn't.

On the last fairly large rails app I tried to use jemalloc on there was no change in memory usage. I believe that advice is a bit outdated. Also note using jemalloc doesn't cause memory to be freed to the system. It reduces fragmentation, at the cost of cpu cycles. There's no free lunch.

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

#120
post #59
post #44

Earlier quoted context omitted.

No one disputes that Ruby is slow. But you picking “mirrors” in your analogy makes it sounds like a premature optimization. The reason why perf isn’t typically an issue with Rails is the design pattern is to leverage heavy caching. The use of caching is to address the slowness of Ruby.

The two major areas where caching is used in Rails are: - database queries - template rendering First one because round trip to db + running the query + allocating ORM result objects that otherwise get thrown away. Second one because allocating a ton of strings that get join'd and thrown away. > No one disputes that Ruby is slow. I am, because the blanket statement doesn't make sense without context. Also that view i…

Ruby without Rails —

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Post reply on HN