GC.stat Mini Series Part Three: Pages
Happy Thursday!
We’ll continue this mini email series with the next piece of the GC.stat
hash: learning more about pages. As we discussed last time when learning about slots, pages are ~16kb chunks of memory, which each contain ~409 slots. Ruby requests memory from the OS in units of pages, and all of the pages together make up what we refer to as the Ruby Heap.
Okay, so what info does GC.stat
give us about pages?
{ :heap_allocated_pages=>347, :heap_sorted_length=>4239, :heap_allocatable_pages=>1, :heap_eden_pages=>346, :heap_tomb_pages=>1, :total_allocated_pages=>4239, :total_freed_pages=>3892, }
Let’s break this down:
:heap_allocated_pages
As the name suggests, this is how many pages are currently in the heap. Last week, we learned about :heap_available_slots
, the total number of slots in the heap. We know that there are ~409 (sometimes 408) slots per page.
And we can actually confirm this with two values from GC.stat
. In a console, GC.stat[:heap_available_slots] / GC.stat[:heap_allocated_pages]
will be somewhere between 408
and 409
. Try it out yourself!
:heap_sorted_length
This number can be a little confusing at first. Sometimes (early on in the life of a process), it’ll be equivalent to, or not much greater than GC.stat[:heap_allocated_pages]
. However, later in a process it will likely be larger. Its value is the size (in pages) of the Ruby Heap. Note that this is different from the allocated pages because some of the pages in the :heap_sorted_length
may not actively be in use. More on this later!
:heap_allocatable_pages
These are pages that the Ruby Heap has already asked for from the OS, but are not currently in use. When Ruby wants more memory, it will use these pages before requesting more memory from the OS.
:heap_eden_pages
Pages can be categorized as either eden pages or tomb pages. Eden pages are pages which are currently in use. They have at least one live slot.
:heap_tomb_pages
Conversely, tomb pages are not currently in use. They don’t have a single slot with a live RVALUE
in them. Ruby can give these pages back to the OS because it’s not actively using them. Compaction can also impact the eden and tomb page counts, since it will move around RVALUE
s in the Ruby Heap. Try out running GC.compact
in a console, and watching it alter the number of eden and tomb pages as it reorganizes RVALUE
s.
:total_allocated_pages
The total
values in GC.stat
are cumulative over the execution of the entire process. They can only increase. :total_allocated_pages
is, as the name suggests, how many pages the process has allocated over its entire lifespan.
:total_freed_pages
Accordingly, :total_freed_pages
is the number of freed pages over the lifespan of the process. It follows that GC.stat[:total_freed_pages] + GC.stat[:heap_allocated_pages] == GC.stat[:total_allocated_pages]
. The Ruby codebase even has a test which verifies this property.
ebook on its way!
Also, I have an announcement to share which I’m very excited about! Before the end of September, I’ll release an ebook about Ruby garbage collection. I’ll send more information to this email list with each subsequent email, including the official release date, and an early bird discount code specifically for folks on this email.
Thanks for following along!
Sent with love from somewhere in the woods,
Jemma