I'm trying to understand the idea behind memory usage in Ruby. I'm currently going through memory issues on my Rails web app and API.
Here's a simple question:
If I load many records inside a variable like so:
users = User.where(work: 'cook')
This would probably hold in my app's memory for the time I'm using this variable, right?
But would it help to free memory by doing the following after I'm done using the variable in my code?
users = nil
Thank you for your help. I'm also open to answers that answer the question on a broader topic.
Ruby apps can use a lot of memory. But why? According to Heroku and Nate Berkopec, a large part of excessive memory usage is caused by memory fragmentation, and by memory overallocation.
The Ruby Garbage Collector module is an interface to Ruby's mark and sweep garbage collection mechanism. While it runs automatically in the background when needed, the GC module lets you call the GC manually whenever required and gain insights into how garbage collection cycles are running.
A memory leak is an unintentional, uncontrolled, and unending increase in memory usage. No matter how small, eventually, a leak will cause your process to run out of memory and crash.
Finding Leaks in Ruby. Detecting a leak is simple enough. You can use GC , ObjectSpace , and the RSS graphs in your APM tool to watch your memory usage increase.
Yes setting users to nil would indeed reduce required memory (very slightly) but it's not necessary as the Garbage Collector will eventually sweep it. In production you should assume your Ruby process will always grow over time and should be periodically restarted if your concerned about memory management. The maximum heap space reduction you'll ever see in ruby is minimal compared to its growth over time so I wouldn't concern yourself with setting large collections to nil to save a few bytes here and there a little earlier than the GC would have swept it anyway. Ruby allocates objects in a heap space that consists of heap pages. Assuming you're using Ruby2.1 or better, the heap space is divided into used (aka Eden) and empty (aka Tomb) heap pages. When instantiating objects, ruby looks for free space in the eden pages first and only if no space is available will it take a page from tomb. When you then overwrite the object with nil, those heap pages are added back to the tomb. Moving pages from the eden to the tomb will reduct heap size slightly however Ruby's Garbage Collector won't drastically reduce it because it assumes if you've created a large collection of objects before, you'll do it again. One book I recommend diving into is "Ruby Performance Optimization" as it goes through ruby's Garbage Collector in depth.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With