Counting Write Barrier Unprotected Objects
Aug 26, 2020 @ 3:29 pmThis is just a quick post mostly as a note to myself (because I forget the jq
commands).
Ruby objects that are not protected with a write barrier must be examined on every minor GC.
That means that any objects in your system that live for a long time and don’t have write barrier protection will cause unnecessary overhead on every minor collection.
Heap dumps will tell you which objects have a write barrier. In Rails apps I use a small script to get a dump of the heap after boot:
require 'objspace'
require 'config/environment'
GC.start
File.open("heap.dump", "wb") do |f|
ObjectSpace.dump_all(output: f)
end
The heap.dump
file will have a list of all of the objects in the heap.
Here is an example of an object with a write barrier:
{"address":"0x7fec1b2ff940", "type":"IMEMO", "class":"0x7fec1b2ffd50", "imemo_type":"ment", "references":["0x7fec1b314908", "0x7fec1b2ffcd8"], "memsize":48, "flags":{"wb_protected":true, "old":true, "uncollectible":true, "marked":true}}
Here is an example of an object without a write barrier:
{"address":"0x7fec1b2ff760", "type":"ICLASS", "class":"0x7fec1a8c0f60", "references":["0x7fec1a8c9250", "0x7fec1b2fefe0"], "memsize":40}
Objects with a write barrier will have "wb_protected":true
in their flags section.
I like to use jq
to process heap dumps.
Here is a command to find all of the unprotected objects, group them by type, then count them up:
$ jq 'select(.flags.wb_protected | not) | .type' heap.dump | sort | uniq -c | sort -n
1 "MATCH"
2 "ARRAY"
5 "ROOT"
9 "FILE"
323 "MODULE"
927 "ICLASS"
1631 "DATA"
All of the objects listed here will be examined on every minor GC. If my Rails app is spending a lot of time in minor GCs, this is a good place to look.
Ruby 2.8 (or 3.0) will eliminate ICLASS
from this list (here is the commit).