Skip to content
This repository
Browse code

Hash inspectors for HAMT and chained bucket.

  • Loading branch information...
commit 0134a9c9150d69386ef064e6e1b644569d19a9bf 1 parent 95aa2ca
Brian Shirai authored August 01, 2011
80  resources/experiments/hash/code/bucket_inspector.rb
... ...
@@ -0,0 +1,80 @@
  1
+class Hash
  2
+  class Inspector
  3
+    def initialize(h)
  4
+      @h = h
  5
+    end
  6
+
  7
+    def entries
  8
+      @h.__entries__
  9
+    end
  10
+
  11
+    def bytes
  12
+      bytes =  Rubinius.memory_size @h
  13
+      bytes += Rubinius.memory_size entries
  14
+      bytes += Rubinius.memory_size @h.instance_variable_get(:@state)
  15
+
  16
+      @h.each_entry do |e|
  17
+        bytes += Rubinius.memory_size(e)
  18
+        bytes += Rubinius.memory_size(e.key)
  19
+        bytes += Rubinius.memory_size(e.value)
  20
+      end
  21
+
  22
+      bytes
  23
+    end
  24
+
  25
+    def occupancy
  26
+      number = 0
  27
+      entries.each { |obj| number += 1 if obj }
  28
+
  29
+      number * 100.0 / entries.size
  30
+    end
  31
+
  32
+    def depth
  33
+      histogram.max { |a, b| a.first <=> b.first }.first
  34
+    end
  35
+
  36
+    def histogram
  37
+      histo = []
  38
+      entries.each do |chain|
  39
+        next unless chain
  40
+
  41
+        depth = 0
  42
+        while chain
  43
+          depth += 1
  44
+          chain = chain.link
  45
+        end
  46
+
  47
+        if x = histo[depth]
  48
+          x[1] += 1
  49
+        else
  50
+          histo[depth] = [depth, 1]
  51
+        end
  52
+      end
  53
+
  54
+      histo.compact
  55
+    end
  56
+
  57
+    def report
  58
+      histo = histogram
  59
+      max = histo.max { |a, b| a.last <=> b.last }
  60
+      min = histo.min { |a, b| a.last <=> b.last }
  61
+      med = histo.sort { |a, b| a.last <=> b.last }[histo.size/2]
  62
+
  63
+      <<-EOR
  64
+Hash::Inspector report for #{@h.object_id}
  65
+
  66
+Items:     #{@h.size}
  67
+Bytes:     #{bytes}
  68
+Depth:     #{depth}
  69
+Table:     #{entries.size}
  70
+Occupancy: #{"%.2f" % occupancy}%
  71
+
  72
+Depth Stats
  73
+  Max:     #{max.first} (#{max.last})
  74
+  Min:     #{min.first} (#{min.last})
  75
+  Median:  #{med.first} (#{med.last})
  76
+  Mean:    #{@h.size / (occupancy / 100 * entries.size).to_i}
  77
+      EOR
  78
+    end
  79
+  end
  80
+end
146  resources/experiments/hash/code/hamt_inspector.rb
... ...
@@ -0,0 +1,146 @@
  1
+class Hash
  2
+  class Inspector
  3
+    def initialize(h)
  4
+      @h = h
  5
+    end
  6
+
  7
+    def table
  8
+      @h.instance_variable_get :@table
  9
+    end
  10
+
  11
+    def visit(&block)
  12
+      return unless table
  13
+
  14
+      table.entries.each do |obj|
  15
+        case obj
  16
+        when Trie
  17
+          yield obj
  18
+          visit_trie(obj, &block)
  19
+        when Entry
  20
+          yield obj
  21
+        when List
  22
+          List.entries.each { |o| yield o }
  23
+        end
  24
+      end
  25
+
  26
+      self
  27
+    end
  28
+
  29
+    def visit_trie(trie, &block)
  30
+      trie.entries.each do |obj|
  31
+        case obj
  32
+        when Entry
  33
+          yield obj
  34
+        when Trie
  35
+          yield obj
  36
+          visit_trie(obj, &block)
  37
+        end
  38
+      end
  39
+    end
  40
+
  41
+    def bytes
  42
+      bytes =  Rubinius.memory_size @h
  43
+      bytes += Rubinius.memory_size @h.instance_variable_get(:@state)
  44
+
  45
+      if table
  46
+        bytes += Rubinius.memory_size table
  47
+        bytes += Rubinius.memory_size table.entries
  48
+      end
  49
+
  50
+      visit do |obj|
  51
+        bytes += Rubinius.memory_size(obj)
  52
+        if obj.kind_of? Entry
  53
+          bytes += Rubinius.memory_size(obj.key)
  54
+          bytes += Rubinius.memory_size(obj.value)
  55
+        end
  56
+      end
  57
+
  58
+      bytes
  59
+    end
  60
+
  61
+    def tries
  62
+      number = 0
  63
+      visit { |obj| number += 1 if obj.kind_of? Trie }
  64
+      number
  65
+    end
  66
+
  67
+    def lists
  68
+      number = 0
  69
+      visit { |obj| number += 1 if obj.kind_of? List }
  70
+      number
  71
+    end
  72
+
  73
+    def depth_histogram
  74
+      histo = []
  75
+
  76
+      visit do |obj|
  77
+        if obj.kind_of? Trie
  78
+          depth = obj.level + 1
  79
+
  80
+          if x = histo[depth]
  81
+            x[1] += 1
  82
+          else
  83
+            histo[depth] = [depth, 1]
  84
+          end
  85
+        end
  86
+      end
  87
+
  88
+      histo.compact
  89
+    end
  90
+
  91
+    def depth
  92
+      depth_histogram.max { |a, b| a.first <=> b.first }.first
  93
+    end
  94
+
  95
+    def branching_histogram
  96
+      histo = Array.new Rubinius::WORDSIZE, 0
  97
+      visit { |obj| histo[obj.entries.size-1] += 1 if obj.kind_of? Trie }
  98
+      histo.map.with_index { |x, i| [i+1, x] }.select { |x| x.last != 0 }
  99
+    end
  100
+
  101
+    def occupancy
  102
+      return 0.0 unless table
  103
+
  104
+      number = 0
  105
+      table.entries.each { |obj| number += 1 if obj }
  106
+
  107
+      number * 100.0 / table.entries.size
  108
+    end
  109
+
  110
+    def report
  111
+      d_histo = depth_histogram
  112
+      d_max = d_histo.max { |a, b| a.last <=> b.last }
  113
+      d_min = d_histo.min { |a, b| a.last <=> b.last }
  114
+      d_med = d_histo.sort { |a, b| a.last <=> b.last }[d_histo.size/2]
  115
+      d_mean = d_histo.inject(0) { |s, x| s += x.first * x.last } / tries
  116
+
  117
+      b_histo = branching_histogram
  118
+      b_max = b_histo.max { |a, b| a.last <=> b.last }
  119
+      b_min = b_histo.min { |a, b| a.last <=> b.last }
  120
+      b_med = b_histo.sort { |a, b| a.last <=> b.last }[b_histo.size/2]
  121
+      b_mean = b_histo.inject(0) { |s, x| s += x.first * x.last } / tries
  122
+
  123
+      <<-EOR
  124
+Hash::Inspector report for #{@h.object_id}
  125
+
  126
+Items:     #{@h.size}
  127
+Bytes:     #{bytes}
  128
+Depth:     #{depth}
  129
+Tries:     #{tries}
  130
+Occupancy: #{"%.2f" % occupancy}%
  131
+
  132
+Depth Stats
  133
+  Max:     #{d_max.first} (#{d_max.last})
  134
+  Min:     #{d_min.first} (#{d_min.last})
  135
+  Median:  #{d_med.first} (#{d_med.last})
  136
+  Mean:    #{d_mean}
  137
+
  138
+Branching Stats
  139
+  Max:     #{b_max.first} (#{b_max.last})
  140
+  Min:     #{b_min.first} (#{b_min.last})
  141
+  Median:  #{b_med.first} (#{b_med.last})
  142
+  Mean:    #{b_mean}
  143
+      EOR
  144
+    end
  145
+  end
  146
+end

0 notes on commit 0134a9c

Please sign in to comment.
Something went wrong with that request. Please try again.