Skip to content
This repository has been archived by the owner on Jul 10, 2018. It is now read-only.

Commit

Permalink
Hash inspectors for HAMT and chained bucket.
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Ford committed Aug 1, 2011
1 parent 95aa2ca commit 0134a9c
Show file tree
Hide file tree
Showing 2 changed files with 226 additions and 0 deletions.
80 changes: 80 additions & 0 deletions resources/experiments/hash/code/bucket_inspector.rb
@@ -0,0 +1,80 @@
class Hash
class Inspector
def initialize(h)
@h = h
end

def entries
@h.__entries__
end

def bytes
bytes = Rubinius.memory_size @h
bytes += Rubinius.memory_size entries
bytes += Rubinius.memory_size @h.instance_variable_get(:@state)

@h.each_entry do |e|
bytes += Rubinius.memory_size(e)
bytes += Rubinius.memory_size(e.key)
bytes += Rubinius.memory_size(e.value)
end

bytes
end

def occupancy
number = 0
entries.each { |obj| number += 1 if obj }

number * 100.0 / entries.size
end

def depth
histogram.max { |a, b| a.first <=> b.first }.first
end

def histogram
histo = []
entries.each do |chain|
next unless chain

depth = 0
while chain
depth += 1
chain = chain.link
end

if x = histo[depth]
x[1] += 1
else
histo[depth] = [depth, 1]
end
end

histo.compact
end

def report
histo = histogram
max = histo.max { |a, b| a.last <=> b.last }
min = histo.min { |a, b| a.last <=> b.last }
med = histo.sort { |a, b| a.last <=> b.last }[histo.size/2]

<<-EOR
Hash::Inspector report for #{@h.object_id}
Items: #{@h.size}
Bytes: #{bytes}
Depth: #{depth}
Table: #{entries.size}
Occupancy: #{"%.2f" % occupancy}%
Depth Stats
Max: #{max.first} (#{max.last})
Min: #{min.first} (#{min.last})
Median: #{med.first} (#{med.last})
Mean: #{@h.size / (occupancy / 100 * entries.size).to_i}
EOR
end
end
end
146 changes: 146 additions & 0 deletions resources/experiments/hash/code/hamt_inspector.rb
@@ -0,0 +1,146 @@
class Hash
class Inspector
def initialize(h)
@h = h
end

def table
@h.instance_variable_get :@table
end

def visit(&block)
return unless table

table.entries.each do |obj|
case obj
when Trie
yield obj
visit_trie(obj, &block)
when Entry
yield obj
when List
List.entries.each { |o| yield o }
end
end

self
end

def visit_trie(trie, &block)
trie.entries.each do |obj|
case obj
when Entry
yield obj
when Trie
yield obj
visit_trie(obj, &block)
end
end
end

def bytes
bytes = Rubinius.memory_size @h
bytes += Rubinius.memory_size @h.instance_variable_get(:@state)

if table
bytes += Rubinius.memory_size table
bytes += Rubinius.memory_size table.entries
end

visit do |obj|
bytes += Rubinius.memory_size(obj)
if obj.kind_of? Entry
bytes += Rubinius.memory_size(obj.key)
bytes += Rubinius.memory_size(obj.value)
end
end

bytes
end

def tries
number = 0
visit { |obj| number += 1 if obj.kind_of? Trie }
number
end

def lists
number = 0
visit { |obj| number += 1 if obj.kind_of? List }
number
end

def depth_histogram
histo = []

visit do |obj|
if obj.kind_of? Trie
depth = obj.level + 1

if x = histo[depth]
x[1] += 1
else
histo[depth] = [depth, 1]
end
end
end

histo.compact
end

def depth
depth_histogram.max { |a, b| a.first <=> b.first }.first
end

def branching_histogram
histo = Array.new Rubinius::WORDSIZE, 0
visit { |obj| histo[obj.entries.size-1] += 1 if obj.kind_of? Trie }
histo.map.with_index { |x, i| [i+1, x] }.select { |x| x.last != 0 }
end

def occupancy
return 0.0 unless table

number = 0
table.entries.each { |obj| number += 1 if obj }

number * 100.0 / table.entries.size
end

def report
d_histo = depth_histogram
d_max = d_histo.max { |a, b| a.last <=> b.last }
d_min = d_histo.min { |a, b| a.last <=> b.last }
d_med = d_histo.sort { |a, b| a.last <=> b.last }[d_histo.size/2]
d_mean = d_histo.inject(0) { |s, x| s += x.first * x.last } / tries

b_histo = branching_histogram
b_max = b_histo.max { |a, b| a.last <=> b.last }
b_min = b_histo.min { |a, b| a.last <=> b.last }
b_med = b_histo.sort { |a, b| a.last <=> b.last }[b_histo.size/2]
b_mean = b_histo.inject(0) { |s, x| s += x.first * x.last } / tries

<<-EOR
Hash::Inspector report for #{@h.object_id}
Items: #{@h.size}
Bytes: #{bytes}
Depth: #{depth}
Tries: #{tries}
Occupancy: #{"%.2f" % occupancy}%
Depth Stats
Max: #{d_max.first} (#{d_max.last})
Min: #{d_min.first} (#{d_min.last})
Median: #{d_med.first} (#{d_med.last})
Mean: #{d_mean}
Branching Stats
Max: #{b_max.first} (#{b_max.last})
Min: #{b_min.first} (#{b_min.last})
Median: #{b_med.first} (#{b_med.last})
Mean: #{b_mean}
EOR
end
end
end

0 comments on commit 0134a9c

Please sign in to comment.