GC.stat Mini Series Part Two: Slots
Hi!
We’re continuing this week with learning about another bit of the output of GC.stat
. GC.stat
is a hash Ruby exposes that can give us incredible insight into what the garbage collector has actually done when running our program. Last week, we learned about different counts that GC.stat
gives us.
Today, we’re going to learn about the slot counts. First, we have to define a slot. Ruby’s entire object space is called the Ruby Heap. When the Ruby Heap needs more memory it requests this memory from the OS (operating system) in units of pages. Pages are ~16kb chunks of memory, which Ruby divides into ~409 slots of 40 bytes each.
Each slot can hold a representation of one object in the form of an RVALUE
. RVALUE
s are Ruby’s internal representation of objects. What if an object is larger than 40 bytes, or larger than the space available in one slot? Then the slot stores a reference to OS memory, outside of the Ruby Heap, which contains the rest of the data needed to represent the object.
Before a slot is filled with an RVALUE
, or after the garbage collector has reallocated a slot, slots can also be empty (or free). This means that Ruby can place a new RVALUE
, or a new object, into the slot!
Okay, now that we know what slots are, let’s look at some of the information that GC.stat
gives us about slots:
{ :heap_available_slots=>84581, :heap_live_slots=>83643, :heap_free_slots=>938, :heap_marked_slots=>56185 }
Fortunately for us, the names of all of these slot-related fields give a clear description of what information they contain!
heap_available_slots
GC.stat[:heap_availabe_slots]
is the total number of slots in our Ruby Heap. We can watch this number grow if we create (and keep a way to reference) many new objects. Try something like objects = 100_000.times.map { Object.new }
in a console, and watch this number increase as Ruby asks the OS for more pages (and slots!) to store the RVALUE
s for these new objects.
heap_live_slots
GC.stat[:heap_live_slots]
gives us the number of slots in the heap which store RVALUE
s that we can accessed.
heap_free_slots
GC.stat[:heap_free_slots]
gives us the number of slots in the heap which don’t have RVALUE
s we can access. This is an important statistic. If it’s extremely high (more than a few hundred thousand), this can be indicative of memory bloat. It means it’s likely that something allocated a huge number of objects and then didn’t need them, bloating the memory that a program is consuming. Conversely, if it’s extremely low, it’s likely that the GC will run soon to try find some more slots Ruby can use before requesting new memory from the OS.
heap_marked_slots
GC.stat[:heap_marked_slots]
is the sum of how many slots have been marked and how many write barrier unprotected objects we have. To learn more about marked slots, check out this post which discusses the algorithm Ruby’s garbage collector uses to determine which objects can have their slots reallocated. Write barrier unprotected objects are relevant to incremental garbage collection, which you can learn more about here.
Slots are changing
Interestingly, there is currently in progress work to change slots to be variable width instead of constant 40 bytes. Check out this Euruko talk by Peter Zhu and Matthew Valentine-House to learn more about the work they’re doing to change the way slots work!
Until next time
Thanks for reading this email. As always, feel free to reply with any thoughts or feedback. I’ll write again soon with more descriptions of parts of the output of GC.stat!
Sent with love from somewhere in the woods,
Jemma