Created
February 2, 2017 02:16
-
-
Save tenderlove/88599d0e3704ad946430a471b9c2e395 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'json' | |
require 'fiddle' | |
module HeapUtils | |
SIZEOF_HEAP_PAGE_HEADER_STRUCT = Fiddle::SIZEOF_VOIDP | |
HEAP_PAGE_ALIGN_LOG = 14 | |
HEAP_PAGE_ALIGN = 1 << HEAP_PAGE_ALIGN_LOG | |
HEAP_PAGE_ALIGN_MASK = ~(~0 << HEAP_PAGE_ALIGN_LOG) | |
# SIZEOF_RVALUE = 56 # Only when GC_DEBUG is enabled | |
SIZEOF_RVALUE = 40 | |
REQUIRED_SIZE_BY_MALLOC = Fiddle::SIZEOF_SIZE_T * 5 # padding needed by malloc | |
HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN - REQUIRED_SIZE_BY_MALLOC | |
HEAP_PAGE_OBJ_LIMIT = (HEAP_PAGE_SIZE - SIZEOF_HEAP_PAGE_HEADER_STRUCT) / SIZEOF_RVALUE | |
def NUM_IN_PAGE object_address | |
(object_address & HEAP_PAGE_ALIGN_MASK) / SIZEOF_RVALUE | |
end | |
def GET_PAGE_BODY object_address | |
object_address & ~HEAP_PAGE_ALIGN_MASK | |
end | |
# Calculate the address given an object id | |
def id_to_addr object_id | |
object_id << 1 | |
end | |
# Calculate page body address from object address | |
def page_addr_from_object_addr object_address | |
GET_PAGE_BODY(object_address) | |
end | |
# Offset from the start of a page. E.g. the address for the 4th object in | |
# a page will return 4 | |
def page_number_from_object_addr object_address | |
NUM_IN_PAGE(object_address) | |
end | |
class Page < Struct.new :addr, :start, :total_slots | |
def finish | |
start + total_slots | |
end | |
end | |
# Get a page given an address | |
def page_for_address addr | |
page page_addr_from_object_addr addr | |
end | |
# Get a page for a live object | |
def page_for_object obj | |
page_for_address id_to_addr obj.object_id | |
end | |
def page page_body | |
limit = HEAP_PAGE_OBJ_LIMIT | |
start = page_body + SIZEOF_HEAP_PAGE_HEADER_STRUCT | |
if start % SIZEOF_RVALUE != 0 | |
delta = SIZEOF_RVALUE - (start % SIZEOF_RVALUE) | |
start = start + delta | |
limit = (HEAP_PAGE_SIZE - (start - page_body)) / SIZEOF_RVALUE | |
end | |
Page.new page_body, start, limit | |
end | |
end | |
include HeapUtils | |
pages = { } | |
File.open(ARGV[0], 'r') do |f| | |
f.each_line do |line| | |
object = JSON.load line | |
if object['type'] != 'ROOT' | |
address = object['address'].to_i 16 | |
page = page_for_address address | |
pages[page.addr] ||= [] | |
pages[page.addr] << object | |
end | |
end | |
end | |
puts "pinned,unpinned,empty" | |
pinning = pages.sort_by { |k,v| v.select { |obj| obj.key?('flags') && obj['flags']['pinned'] }.length }.reverse | |
pinning.each do |page_addr, objs| | |
page_obj = page_for_address page_addr | |
pinned = objs.select { |o| o.key?('flags') && o['flags']['pinned'] }.length | |
empty = page_obj.total_slots - objs.length | |
puts "#{pinned},#{objs.length - pinned},#{empty}" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment