Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / scripts / mono-heapviz
index c0ae0ef4baf8f13b70384ad1ae0ff8bf64fd2782..27b6f7f60235790c7c55fbd5748b9698f25de6a8 100755 (executable)
@@ -8,7 +8,7 @@
 from __future__ import print_function
 import sys, os
 import Image, ImageDraw
-from xml.sax import ContentHandler, saxutils, make_parser
+from xml.sax import ContentHandler, make_parser
 from xml.sax.handler import feature_namespaces
 from optparse import OptionParser
 
@@ -92,8 +92,11 @@ class SmallSectionHandler (SectionHandler):
         assert kind == 'old'
         if self.width <= 0:
             self.width = (size + chunk_size - 1) / chunk_size
-        else:
-            assert self.width == (size + chunk_size - 1) / chunk_size
+            if self.width < 128:
+                self.width = 512
+                self.current_section_size = size
+            else:
+                self.current_section_size = self.width * chunk_size
         self.size += size
 
     def add_object (self, klass, offset, size):
@@ -103,14 +106,14 @@ class SmallSectionHandler (SectionHandler):
         SectionHandler.add_occupied (self, self.offset + offset, size)
 
     def end_section (self):
-        self.offset += self.width * chunk_size
+        self.offset += self.current_section_size
 
     def header (self):
         return 'old sections'
 
 class LargeSectionHandler (SectionHandler):
     def __init__ (self):
-        SectionHandler.__init__ (self, 500)
+        SectionHandler.__init__ (self, 512)
 
     def start_section (self, kind, size):
         self.kind = kind
@@ -124,7 +127,7 @@ class LargeSectionHandler (SectionHandler):
     def header (self):
         return self.kind + ' section'
 
-class DocHandler (saxutils.DefaultHandler):
+class DocHandler (ContentHandler):
     def start (self):
         self.collection_index = 0
         self.index_file = open ('index.html', 'w')
@@ -152,7 +155,10 @@ class DocHandler (saxutils.DefaultHandler):
             print ('<h1>%s collection %d</h1>' % (self.collection_kind, self.collection_num), file = self.collection_file)
             self.usage = {}
             self.los_usage = {}
+            self.pinned_usage = {}
+            self.occupancies = {}
             self.in_los = False
+            self.in_pinned = False
             self.heap_used = 0
             self.heap_size = 0
             self.los_size = 0
@@ -164,6 +170,13 @@ class DocHandler (saxutils.DefaultHandler):
             kind = attrs.get('type', None)
             bytes = int(attrs.get('bytes', None))
             print ('Pinned from %s: %d kB<br>' % (kind, bytes / 1024), file = self.collection_file)
+        elif name == 'occupancy':
+            size = int (attrs.get ('size', None))
+            available = int (attrs.get ('available', None))
+            used = int (attrs.get ('used', None))
+            unused = available - used
+
+            print ('Occupancy of %d byte slots: %d / %d (%d kB / %d%% wasted)<br>' % (size, used, available, unused * size / 1024, unused * 100 / available), file = self.collection_file)
         elif name == 'section':
             kind = attrs.get('type', None)
             size = int(attrs.get('size', None))
@@ -184,6 +197,11 @@ class DocHandler (saxutils.DefaultHandler):
             if self.in_los:
                 usage_dict = self.los_usage
                 self.los_size += size
+            elif self.in_pinned:
+                location = attrs.get('location', None)
+                if location not in self.pinned_usage:
+                    self.pinned_usage[location] = {}
+                usage_dict = self.pinned_usage[location]
             else:
                 usage_dict = self.usage
                 offset = int(attrs.get('offset', None))
@@ -202,6 +220,8 @@ class DocHandler (saxutils.DefaultHandler):
             self.heap_used += size
         elif name == 'los':
             self.in_los = True
+        elif name == 'pinned-objects':
+            self.in_pinned = True
 
     def dump_usage (self, usage_dict, limit):
         klasses = sorted (usage_dict.keys (), lambda x, y: usage_dict [y][1] - usage_dict [x][1])
@@ -229,12 +249,18 @@ class DocHandler (saxutils.DefaultHandler):
             self.dump_usage (self.usage, 10)
             print ('<h3>LOS</h3>', file = self.collection_file)
             self.dump_usage (self.los_usage, None)
+            print ('<h3>Pinned</h3>', file = self.collection_file)
+            for location in sorted (self.pinned_usage.keys ()):
+                print ('<h4>%s</h4>' % location, file = self.collection_file)
+                self.dump_usage (self.pinned_usage[location], None)
             print ('</body></html>', file = self.collection_file)
             print (' - %d kB / %d kB (%d%%) - %d kB LOS</a><br>' % (self.heap_used / 1024, self.heap_size / 1024, int(100.0 * self.heap_used / self.heap_size), self.los_size / 1024), file = self.index_file)
             self.collection_file.close ()
             self.collection_index += 1
         elif name == 'los':
             self.in_los = False
+        elif name == 'pinned-objects':
+            self.in_pinned = False
 
 def main ():
     usage = "usage: %prog [options]"