• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
7import collections
8import gzip
9import json
10
11
12def FormatBytes(value):
13  units = ['B', 'KiB', 'MiB', 'GiB']
14  while abs(value) >= 1024 and len(units) > 1:
15    value /= 1024
16    units = units.pop(0)
17  return '%3.1f %s' % (value, units[0])
18
19
20def 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)
101