Ruby Garbage Collection Deep Dive: GC::INTERNAL_CONSTANTS
jemma.dev
jemma.dev
I've just realized that I was asked about this stuff in almost every Java interview I had, sometimes the questions were very detailed (and I was nowhere near HFT or any other real-time systems, GC pauses were minor concerns) but for jobs focused on other languages this topic is almost completely skipped.
It was in the context of a sidekiq job that was importing customer data via csv file. We would read in the csv, and for each row a lot of complicated logic was being performed that would translate the data from customer format into our format, and decide how to update different tables in db. These files were sometimes 10k lines or longer (all handled by a single sidekiq job), and would balloon up in memory so much that sidekiq would crash and would keep trying to restart the job. For each row we were instantiating an ActiveModel object that had a lot of attributes/functions. I think the right solution would have probably been to do a (fairly heavy) refactor of that area in the code, and spin up a separate job for each row, but we found that by running a GC.start every few rows we were able to cleanup some of the old AM objects and keep the memory usage low for the time being...
The defaults seem very good, even at scale.
I've been doing Ruby since 2014. Mostly Rails, but also a bunch of data processing.
I have run into memory issues at times, when shuffling large amounts of data around. But manually running GC was never the answer in my cases.
In all cases, the memory issues were because I'd created a bunch of heavy objects that were still in-scope and were therefore not eligible to be cleaned up by GC anyway.
This was all Ruby 2.0+ and most of the heavy data processing stuff was 2.3+. So I wasn't doing any of it back in the days of really ancient Ruby GC.
I'll say this much: When I was working on these applications, one of the minor wins that I had was swapping them over to the jemalloc memory allocator. It has introspection/instrumentation tooling that is really useful for these sorts of situations. You can use `MALLOC_CONF` [0] to trigger some built-in profiling. For instance, `export MALLOC_CONF='prof_leak:true,lg_prof_sample:0,prof_final:true'` will trigger jemalloc to log the heap at exit which is very useful for tracking down leaks.
[0]: https://github.com/jemalloc/jemalloc/wiki/Use-Case%3A-Leak-C...
I think the app that needed to be the most performant ended up using JRuby :P
I can't wait for truffleruby to be a thing.
Having a limit for the VM is helpful. Also, by default it is automatically 20% of available memory.
Personally, I've had to tune this kind of stuff with every VM I worked with (JVM, Node, PHP). :)
I'm additionally amazed at people who show up at the interview sometimes claiming C and/or C++ experience (completely not required for the role, but hey, they do claim that experience) but then seem to be completely unaware of any basics of memory management.
Because I’m helping on a Rails app I’m learning a lot of magic, which is awesome for productivity, but I feel like I’m missing some important concepts that tie things together.
I learned quite a bit about ruby memory mgmt from the above. Free text, pay for video tutorials IIRC. The course was authored by Nate Berkopec.
https://www.youtube.com/user/nateberkopec
I also found "the well grounded rubyist" to be very helpful.
https://www.manning.com/books/the-well-grounded-rubyist-thir...
http://journal.stuffwithstuff.com/2013/12/08/babys-first-gar...
Ruby Garbage Collection Deep Dive: Tri-Color Mark and Sweep - https://news.ycombinator.com/item?id=26182796 - Feb 2021 (15 comments)