def main(args): snapshot = Snapshot.FromJSONFile( sys.stdin) if args.snapshot is None else Snapshot.FromJSONFilename( args.snapshot) vmo_to_count = {} for p in snapshot.processes.values(): for v in p.vmos: if v.koid in vmo_to_count: vmo_to_count[v.koid] += 1 else: vmo_to_count[v.koid] = 1 nodes = [] snaphot_name = 'Snapshot' kernel_name = 'Kernel' nodes.append(["Orphaned", snaphot_name, 0]) nodes.append(["Orphaned VMOs", "Orphaned", snapshot.orphaned]) nodes.append([kernel_name, snaphot_name, 0]) nodes.append(["Wired", kernel_name, snapshot.kernel.wired]) nodes.append(["Heap", kernel_name, snapshot.kernel.total_heap]) nodes.append(["IPC", kernel_name, snapshot.kernel.ipc]) nodes.append(["Other", kernel_name, snapshot.kernel.other]) nodes.append(["MMU", kernel_name, snapshot.kernel.mmu]) for p in snapshot.processes.values(): process_name = "%s<%d>" % (p.name, p.koid) nodes.append([process_name, snaphot_name, 0]) groups = {} for v in p.vmos: group_name = None for gs in group_specs: if gs[1].match(v.name): group_name = "%s<%d>" % (gs[0], p.koid) if gs[0] not in groups: nodes.append([group_name, process_name, 0]) groups[gs[0]] = True break vmo_name = "%s<%d:%d>" % (v.name, p.koid, v.koid) nodes.append([ vmo_name, process_name if group_name is None else group_name, float(v.committed_bytes) / vmo_to_count[v.koid] ]) template = '''\ <html> <head> <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> <script type="text/javascript"> google.charts.load('current', {'packages':['treemap']}); google.charts.setOnLoadCallback(drawChart); function drawChart() { var data = google.visualization.arrayToDataTable([ ['Process','Parent','Size (MB)'], ['Snapshot',null,0], %s ]); tree = new google.visualization.TreeMap(document.getElementById('chart_div')); tree.draw(data, { headerHeight: 15, fontColor: 'black', generateTooltip: showTooltip, maxDepth: 2, enableHighlight: true, minHighlightColor: '#8c6bb1', midHighlightColor: '#9ebcda', maxHighlightColor: '#edf8fb', minColor: '#009688', midColor: '#f7f7f7', maxColor: '#ee8100' }); function showTooltip(row, size, value) { return '<div style="background:#fd9; padding:10px; border-style:solid">' + data.getValue(row, 0) + ' ' + size.toFixed(2) + 'MB</div>'; } } </script> </head> <body> <div id="chart_div" style="width: 100%%; height: 100%%;"></div> </body> </html> ''' node_strings = '\n'.join([ "[\'%s\',\'%s\',%.2g]," % (n[0], n[1], round(n[2] / (1024.0 * 1024), 2)) for n in nodes ]) print(template % node_strings)
def main(args): snapshot = Snapshot.FromJSONFile( sys.stdin) if args.snapshot is None else Snapshot.FromJSONFilename( args.snapshot) digest = Digest.FromJSONFilename(snapshot, args.digest) buckets = sorted(digest.buckets.values(), key=lambda b: b.name) if (args.output == "csv"): for bucket in buckets: print("%s, %d" % (bucket.name, bucket.size)) elif (args.output == "html"): output_html(buckets) else: total = 0 for bucket in buckets: if bucket.size == 0: continue print("%s: %s" % (bucket.name, fmt_size(bucket.size))) total += bucket.size if bucket.name != "Undigested" and bucket.processes and args.verbose: entries = [] for processes, vmos in bucket.processes.items(): size = sum([v.committed_bytes for v in vmos]) assert size assert len(processes) == 1 entries.append((processes[0].name, size)) # Reverse sort by size. entries.sort(key=lambda t: t[1], reverse=True) for name, size in entries: print("\t%s: %s" % (name, fmt_size(size))) print("\nTotal: %s" % (fmt_size(total))) undigested = digest.buckets["Undigested"] if undigested.processes: print("\nUndigested:") entries = [] for processes, vmos in undigested.processes.items(): size = sum([v.committed_bytes for v in vmos]) assert size entries.append((processes, size, vmos)) # Sort by largest sharing pool, then size def cmp(entry_a, entry_b): if len(entry_b[0]) - len(entry_a[0]): return len(entry_b[0]) - len(entry_a[0]) return entry_b[1] - entry_a[1] entries.sort(key=functools.cmp_to_key(cmp)) for processes, size, vmos in entries: names = [p.full_name for p in processes] print("\t%s: %s" % (" ,".join(names), fmt_size(size))) for process in processes: if args.verbose: # Group by VMO name, store count and total. print("\t\t%s VMO Summaries:" % process.full_name) groups = {} for v in vmos: cnt, ttl = groups.get(v.name, (0, 0)) groups[v.name] = (cnt + 1, ttl + v.committed_bytes) for name, (count, total) in sorted(groups.items(), key=lambda kv: kv[1][1], reverse=True): print( "\t\t\t%s (%d): %s" % (name, count, fmt_size(total))) elif args.extra_verbose: # Print "em all print("\t\t%s VMOs:" % process.full_name) for v in sorted(vmos, key=lambda v: v.name): print( "\t\t\t%s[%d]: %s" % (v.name, v.koid, fmt_size(v.committed_bytes)))