Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: tools/android/loading/pull_sandwich_metrics.py

Issue 1690813003: sandwich: Builds a script to pull the metrics from the traces (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@d01
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #! /usr/bin/env python
2 # Copyright 2016 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Pull a sandwich run's output directory's metrics from traces into a CSV.
7
8 python pull_sandwich_metrics.py -h
mattcary 2016/02/12 09:59:47 With the #! line, this can be run directly without
gabadie 2016/02/12 10:39:11 Oups yes indeed... Done.
9 """
10
11 import argparse
12 import csv
13 import json
14 import logging
15 import os
16 import sys
17
18
19 CATEGORIES = ['blink.user_timing', 'disabled-by-default-memory-infra']
20 _CSV_FIELD_NAMES = [
21 'id',
22 'total_load',
23 'onload',
24 'browser_malloc_avg',
25 'browser_malloc_max']
26
27 _TRACKED_EVENT_NAMES = set(['requestStart', 'loadEventStart', 'loadEventEnd'])
28
29 def _GetBrowserPID(trace):
Benoit L 2016/02/12 10:26:41 nit: Here and below, 2 lines between top-level dec
gabadie 2016/02/12 10:39:11 Done.
30 """Get the browser PID from a trace.
31
32 Args:
33 trace: The cached trace.
34
35 Returns:
36 The browser's PID as an integer.
37 """
38 for event in trace['traceEvents']:
39 if event['cat'] != '__metadata' or event['name'] != 'process_name':
40 continue
41 if event['args']['name'] == 'Browser':
42 return event['pid']
43 raise Exception('couldn\'t find browser\'s PID')
44
45 def _GetBrowserDumpEvents(trace):
46 """Get the browser memory dump events from a trace.
47
48 Args:
49 trace: The cached trace.
50
51 Returns:
52 List of memory dump events.
53 """
54 browser_pid = _GetBrowserPID(trace)
55 browser_dumps_events = []
56 for event in trace['traceEvents']:
57 if event['cat'] != 'disabled-by-default-memory-infra':
58 continue
59 if event['ph'] != 'v' or event['name'] != 'periodic_interval':
60 continue
61 # Ignore dumps event for processes other than the browser process
Benoit L 2016/02/12 10:26:41 s/dumps event/dump events/
gabadie 2016/02/12 10:39:11 Done.
62 if event['pid'] != browser_pid:
63 continue
64 browser_dumps_events.append(event)
65 if len(browser_dumps_events) == 0:
66 raise Exception('No browser dump events found.')
Benoit L 2016/02/12 10:26:41 ValueError, as pointed out below.
gabadie 2016/02/12 10:39:11 Done.
67 return browser_dumps_events
68
69 def _GetWebPageTrackedEvents(trace):
70 """Get the web page's tracked events from a trace.
71
72 Args:
73 trace: The cached trace.
74
75 Returns:
76 Dictionary all tracked events.
77 """
78 main_frame = None
79 tracked_events = {}
80 for event in trace['traceEvents']:
81 if event['cat'] != 'blink.user_timing':
82 continue
83 event_name = event['name']
84 # Ignore events until about:blank's unloadEventEnd that give the main
85 # frame id.
86 if not main_frame:
87 if event_name == 'unloadEventEnd':
88 main_frame = event['args']['frame']
89 logging.info('found about:blank\'s event \'unloadEventEnd\'')
90 continue
91 # Ignore sub-frames events. requestStart don't have the frame set but it
92 # is fine since tracking the first one after about:blank's unloadEventEnd.
93 if 'frame' in event['args'] and event['args']['frame'] != main_frame:
94 continue
95 if event_name in _TRACKED_EVENT_NAMES and event_name not in tracked_events:
96 logging.info('found url\'s event \'%s\'' % event_name)
97 tracked_events[event_name] = event
98 assert len(tracked_events) == len(_TRACKED_EVENT_NAMES)
99 return tracked_events
100
101 def _PullMetricsFromTrace(trace):
102 """Pulls all the metrics from a given trace.
103
104 Args:
105 trace: The cached trace.
106
107 Returns:
108 Dictionary with all _CSV_FIELD_NAMES's field set (except the 'id').
109 """
110 browser_dumps_events = _GetBrowserDumpEvents(trace)
Benoit L 2016/02/12 10:26:41 s/browser_dumps_events/browser_dump_events/
gabadie 2016/02/12 10:39:11 Done.
111 web_page_tracked_events = _GetWebPageTrackedEvents(trace)
112
113 browser_malloc_avg = 0
Benoit L 2016/02/12 10:26:41 Arguably, this is not an average, but OK.
gabadie 2016/02/12 10:39:11 Renaming as *_sum. Done.
114 browser_malloc_max = 0
115 for dump_event in browser_dumps_events:
116 attr = dump_event['args']['dumps']['allocators']['malloc']['attrs']['size']
117 assert attr['units'] == 'bytes'
118 size = int(attr['value'], 16)
Benoit L 2016/02/12 10:26:41 size is serialized as an hex string? Weird.
gabadie 2016/02/12 10:39:11 Totally agree.
119 browser_malloc_avg += size
120 browser_malloc_max = max(browser_malloc_max, size)
121
122 return {
123 'total_load': (web_page_tracked_events['loadEventEnd']['ts'] -
124 web_page_tracked_events['requestStart']['ts']),
125 'onload': (web_page_tracked_events['loadEventEnd']['ts'] -
126 web_page_tracked_events['loadEventStart']['ts']),
127 'browser_malloc_avg': browser_malloc_avg / float(len(browser_dumps_events)),
128 'browser_malloc_max': browser_malloc_max
129 }
130
131 def _PullMetricsFromOutputDirectory(output_directory_path):
132 """Pulls all the metrics from all the traces of a sandwich run directory.
133
134 Args:
135 output_directory_path: The sandwich run's output directory to pull the
136 metrics from.
137
138 Returns:
139 List of dictionaries with all _CSV_FIELD_NAMES's field set.
140 """
141 assert os.path.isdir(output_directory_path)
142 metrics = []
143 for node_name in os.listdir(output_directory_path):
144 if not os.path.isdir(os.path.join(output_directory_path, node_name)):
145 continue
146 try:
147 page_id = int(node_name)
148 except Exception:
mattcary 2016/02/12 09:59:47 ValueError would be better than catching all excep
Benoit L 2016/02/12 10:26:41 Pokemon exception handling: gotta catch'em all!
gabadie 2016/02/12 10:39:11 Done.
mattcary 2016/02/12 10:41:11 But continuing isn't actually catching them... it'
149 continue
150 trace_path = os.path.join(output_directory_path, node_name, 'trace.json')
151 if not os.path.isfile(trace_path):
152 continue
153 logging.info('processing \'%s\'' % trace_path)
154 with open(trace_path) as trace_file:
155 trace = json.load(trace_file)
156 trace_metrics = _PullMetricsFromTrace(trace)
157 trace_metrics['id'] = page_id
158 metrics.append(trace_metrics)
159 assert len(metrics) > 0, ('Looks like \'{}\' was not a sandwich ' +
160 'run directory.').format(output_directory_path)
161 return metrics
162
163 def main():
164 logging.basicConfig(level=logging.INFO)
165
166 parser = argparse.ArgumentParser()
167 parser.add_argument('output', type=str,
168 help='Output directory of run_sandwich.py command.')
169 args = parser.parse_args()
170
171 trace_metrics_list = _PullMetricsFromOutputDirectory(args.output)
172 trace_metrics_list.sort(key=lambda e: e['id'])
173 cs_file_path = os.path.join(args.output, 'trace_analysis.csv')
174 with open(cs_file_path, 'w') as csv_file:
175 writer = csv.DictWriter(csv_file, fieldnames=_CSV_FIELD_NAMES)
176 writer.writeheader()
177 for trace_metrics in trace_metrics_list:
178 writer.writerow(trace_metrics)
179 return 0
180
181 if __name__ == '__main__':
182 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698