| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Filters a big trace keeping only the last memory-infra dumps.""" |
| 6 |
| 7 import collections |
| 8 import gzip |
| 9 import json |
| 10 |
| 11 |
| 12 def FormatBytes(value): |
| 13 units = ['B', 'kB', 'MB', 'GB'] |
| 14 while abs(value) >= 1000 and len(units) > 1: |
| 15 value /= 1000 |
| 16 units = units.pop(0) |
| 17 return '%3.1f %s' % (value, units[0]) |
| 18 |
| 19 |
| 20 def Main(argv): |
| 21 if len(argv) < 2: |
| 22 print 'Usage: %s trace.json[.gz]' % argv[0] |
| 23 return 1 |
| 24 |
| 25 in_path = argv[1] |
| 26 if in_path.lower().endswith('.gz'): |
| 27 fin = gzip.open(in_path, 'rb') |
| 28 else: |
| 29 fin = open(in_path, 'r') |
| 30 with fin: |
| 31 print 'Loading trace (can take 1 min on a z620 for a 1GB trace)...' |
| 32 trace = json.load(fin) |
| 33 print 'Done. Read ' + FormatBytes(fin.tell()) |
| 34 |
| 35 print 'Filtering events' |
| 36 phase_count = collections.defaultdict(int) |
| 37 out_events = [] |
| 38 global_dumps = collections.OrderedDict() |
| 39 if isinstance(trace, dict): |
| 40 in_events = trace.get('traceEvents', []) |
| 41 elif isinstance(trace, list) and isinstance(trace[0], dict): |
| 42 in_events = trace |
| 43 |
| 44 for evt in in_events: |
| 45 phase = evt.get('ph', '?') |
| 46 phase_count[phase] += 1 |
| 47 |
| 48 # Drop all diagnostic events for memory-infra debugging. |
| 49 if phase not in ('v', 'V') and evt.get('cat', '').endswith('memory-infra'): |
| 50 continue |
| 51 |
| 52 # pass-through all the other non-memory-infra events |
| 53 if phase != 'v': |
| 54 out_events.append(evt) |
| 55 continue |
| 56 |
| 57 # Recreate the global dump groups |
| 58 event_id = evt['id'] |
| 59 global_dumps.setdefault(event_id, []) |
| 60 global_dumps[event_id].append(evt) |
| 61 |
| 62 |
| 63 print 'Detected %d memory-infra global dumps' % len(global_dumps) |
| 64 if global_dumps: |
| 65 max_procs = max(len(x) for x in global_dumps.itervalues()) |
| 66 print 'Max number of processes seen: %d' % max_procs |
| 67 |
| 68 ndumps = 2 |
| 69 print 'Preserving the last %d memory-infra dumps' % ndumps |
| 70 detailed_dumps = [] |
| 71 non_detailed_dumps = [] |
| 72 for global_dump in global_dumps.itervalues(): |
| 73 try: |
| 74 level_of_detail = global_dump[0]['args']['dumps']['level_of_detail'] |
| 75 except KeyError: |
| 76 level_of_detail = None |
| 77 if level_of_detail == 'detailed': |
| 78 detailed_dumps.append(global_dump) |
| 79 else: |
| 80 non_detailed_dumps.append(global_dump) |
| 81 |
| 82 dumps_to_preserve = detailed_dumps[-ndumps:] |
| 83 ndumps -= len(dumps_to_preserve) |
| 84 if ndumps: |
| 85 dumps_to_preserve += non_detailed_dumps[-ndumps:] |
| 86 |
| 87 for global_dump in dumps_to_preserve: |
| 88 out_events += global_dump |
| 89 |
| 90 print '\nEvents histogram for the original trace (count by phase)' |
| 91 print '--------------------------------------------------------' |
| 92 for phase, count in sorted(phase_count.items(), key=lambda x: x[1]): |
| 93 print '%s %d' % (phase, count) |
| 94 |
| 95 out_path = in_path.split('.json')[0] + '-filtered.json' |
| 96 print '\nWriting filtered trace to ' + out_path, |
| 97 with open(out_path, 'w') as fout: |
| 98 json.dump({'traceEvents': out_events}, fout) |
| 99 num_bytes_written = fout.tell() |
| 100 print ' (%s written)' % FormatBytes(num_bytes_written) |
| OLD | NEW |