Jemma

Subscribe
Archives
September 9, 2021

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 RVALUEs 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 RVALUEs.

: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

Don't miss what's next. Subscribe to Jemma:
Powered by Buttondown, the easiest way to start and grow your newsletter.