Chromium Code Reviews| 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[1:] | |
|
perezju
2016/07/27 10:28:14
nit: units.pop(0)
Primiano Tucci (use gerrit)
2016/07/27 10:38:03
Done.
| |
| 17 return '%3.1f %s' % (value, units[0]) | |
| 18 | |
|
perezju
2016/07/27 10:28:13
nit: extra blank line needed
Primiano Tucci (use gerrit)
2016/07/27 10:38:03
Done.
| |
| 19 def Main(argv): | |
| 20 if len(argv) < 2: | |
| 21 print 'Usage: %s trace.json[.gz]' % argv[0] | |
| 22 return 1 | |
| 23 | |
| 24 in_path = argv[1] | |
| 25 if in_path.lower().endswith('.gz'): | |
| 26 fin = gzip.open(in_path, 'rb') | |
| 27 else: | |
| 28 fin = open(in_path, 'r') | |
| 29 | |
| 30 out_path = in_path.split('.json')[0] + '-filtered.json' | |
|
perezju
2016/07/27 10:28:14
I would move this line to either before opening th
Primiano Tucci (use gerrit)
2016/07/27 10:38:03
Done.
| |
| 31 | |
| 32 print 'Loading trace (can take 1 min on a z620 for a 1GB trace)...' | |
| 33 trace = json.load(fin) | |
| 34 print 'Done. Read ' + FormatBytes(fin.tell()) | |
| 35 fin.close() | |
|
perezju
2016/07/27 10:28:14
Here you could still do
with fin:
print 'Lo
Primiano Tucci (use gerrit)
2016/07/27 10:38:03
ah, TIL
| |
| 36 | |
| 37 print 'Filtering events' | |
| 38 phase_count = collections.defaultdict(int) | |
| 39 out_events = [] | |
| 40 global_dumps = collections.OrderedDict() | |
| 41 if isinstance(trace, dict): | |
| 42 in_events = trace.get('traceEvents', []) | |
| 43 elif isinstance(trace, list) and isinstance(trace[0], dict): | |
| 44 in_events = trace | |
| 45 | |
| 46 for evt in in_events: | |
| 47 phase = evt.get('ph', '?') | |
| 48 phase_count[phase] += 1 | |
| 49 | |
| 50 # Drop all diagnostic events for memory-infra debugging. | |
| 51 if phase not in ('v', 'V') and evt.get('cat', '').endswith('memory-infra'): | |
| 52 continue | |
| 53 | |
| 54 # pass-through all the other non-memory-infra events | |
| 55 if phase != 'v': | |
| 56 out_events.append(evt) | |
| 57 continue | |
| 58 | |
| 59 # Recreate the global dump groups | |
| 60 event_id = evt['id'] | |
| 61 global_dumps.setdefault(event_id, []) | |
| 62 global_dumps[event_id].append(evt) | |
| 63 | |
| 64 | |
| 65 print 'Detected %d memory-infra global dumps' % len(global_dumps) | |
| 66 if global_dumps: | |
| 67 max_procs = max(len(x) for x in global_dumps.itervalues()) | |
| 68 print 'Max number of processes seen: %d' % max_procs | |
| 69 | |
| 70 ndumps = 2 | |
|
perezju
2016/07/27 10:28:14
should this be an arg one can pass from the comman
Primiano Tucci (use gerrit)
2016/07/27 10:38:03
yeah I was thinking to that, but honestly want to
perezju
2016/07/27 11:02:23
stgm :)
| |
| 71 print 'Preserving the last %d memory-infra dumps' % ndumps | |
| 72 detailed_dumps = [] | |
| 73 non_detailed_dumps = [] | |
| 74 for global_dump in global_dumps.itervalues(): | |
| 75 lod = global_dump[0].get('args', {}).get('dumps', {}).get('level_of_detail') | |
|
perezju
2016/07/27 10:28:13
here this would be clearer/easier:
try:
lod
Primiano Tucci (use gerrit)
2016/07/27 10:38:03
Ah brilliant.
| |
| 76 if lod == 'detailed': | |
| 77 detailed_dumps.append(global_dump) | |
| 78 else: | |
| 79 non_detailed_dumps.append(global_dump) | |
| 80 | |
| 81 dumps_to_preserve = detailed_dumps[-ndumps:] | |
|
perezju
2016/07/27 10:28:14
nit: you could
ndumps -= len(dumps_to_preserve)
Primiano Tucci (use gerrit)
2016/07/27 10:38:03
Done.
| |
| 82 if len(dumps_to_preserve) < ndumps: | |
| 83 dumps_to_preserve += non_detailed_dumps[-(ndumps - len(dumps_to_preserve)):] | |
| 84 | |
| 85 for global_dump in dumps_to_preserve: | |
| 86 out_events += global_dump | |
| 87 | |
| 88 print '\nEvents histogram for the original trace (count by phase)' | |
| 89 print '--------------------------------------------------------' | |
| 90 for phase, count in sorted(phase_count.items(), key=lambda x: x[1]): | |
| 91 print '%s %d' % (phase, count) | |
| 92 | |
| 93 print '\nWriting filtered trace to ' + out_path, | |
| 94 with open(out_path, 'w') as fout: | |
| 95 json.dump({'traceEvents': out_events}, fout) | |
| 96 num_bytes_written = fout.tell() | |
| 97 print ' (%s written)' % FormatBytes(num_bytes_written) | |
| OLD | NEW |