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

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: Addresses all review concerns 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
« no previous file with comments | « no previous file | tools/android/loading/pull_sandwich_metrics_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
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
21 _CSV_FIELD_NAMES = [
22 'id',
23 'total_load',
24 'onload',
25 'browser_malloc_avg',
26 'browser_malloc_max']
27
28 _TRACKED_EVENT_NAMES = set(['requestStart', 'loadEventStart', 'loadEventEnd'])
29
30
31 def _GetBrowserPID(trace):
32 """Get the browser PID from a trace.
33
34 Args:
35 trace: The cached trace.
36
37 Returns:
38 The browser's PID as an integer.
39 """
40 for event in trace['traceEvents']:
41 if event['cat'] != '__metadata' or event['name'] != 'process_name':
42 continue
43 if event['args']['name'] == 'Browser':
44 return event['pid']
45 raise ValueError('couldn\'t find browser\'s PID')
46
47
48 def _GetBrowserDumpEvents(trace):
49 """Get the browser memory dump events from a trace.
50
51 Args:
52 trace: The cached trace.
53
54 Returns:
55 List of memory dump events.
56 """
57 browser_pid = _GetBrowserPID(trace)
58 browser_dumps_events = []
59 for event in trace['traceEvents']:
60 if event['cat'] != 'disabled-by-default-memory-infra':
61 continue
62 if event['ph'] != 'v' or event['name'] != 'periodic_interval':
63 continue
64 # Ignore dump events for processes other than the browser process
65 if event['pid'] != browser_pid:
66 continue
67 browser_dumps_events.append(event)
68 if len(browser_dumps_events) == 0:
69 raise ValueError('No browser dump events found.')
70 return browser_dumps_events
71
72
73 def _GetWebPageTrackedEvents(trace):
74 """Get the web page's tracked events from a trace.
75
76 Args:
77 trace: The cached trace.
78
79 Returns:
80 Dictionary all tracked events.
81 """
82 main_frame = None
83 tracked_events = {}
84 for event in trace['traceEvents']:
85 if event['cat'] != 'blink.user_timing':
86 continue
87 event_name = event['name']
88 # Ignore events until about:blank's unloadEventEnd that give the main
89 # frame id.
90 if not main_frame:
91 if event_name == 'unloadEventEnd':
92 main_frame = event['args']['frame']
93 logging.info('found about:blank\'s event \'unloadEventEnd\'')
94 continue
95 # Ignore sub-frames events. requestStart don't have the frame set but it
96 # is fine since tracking the first one after about:blank's unloadEventEnd.
97 if 'frame' in event['args'] and event['args']['frame'] != main_frame:
98 continue
99 if event_name in _TRACKED_EVENT_NAMES and event_name not in tracked_events:
100 logging.info('found url\'s event \'%s\'' % event_name)
101 tracked_events[event_name] = event
102 assert len(tracked_events) == len(_TRACKED_EVENT_NAMES)
103 return tracked_events
104
105
106 def _PullMetricsFromTrace(trace):
107 """Pulls all the metrics from a given trace.
108
109 Args:
110 trace: The cached trace.
111
112 Returns:
113 Dictionary with all _CSV_FIELD_NAMES's field set (except the 'id').
114 """
115 browser_dump_events = _GetBrowserDumpEvents(trace)
116 web_page_tracked_events = _GetWebPageTrackedEvents(trace)
117
118 browser_malloc_sum = 0
119 browser_malloc_max = 0
120 for dump_event in browser_dump_events:
121 attr = dump_event['args']['dumps']['allocators']['malloc']['attrs']['size']
122 assert attr['units'] == 'bytes'
123 size = int(attr['value'], 16)
124 browser_malloc_sum += size
125 browser_malloc_max = max(browser_malloc_max, size)
126
127 return {
128 'total_load': (web_page_tracked_events['loadEventEnd']['ts'] -
129 web_page_tracked_events['requestStart']['ts']),
130 'onload': (web_page_tracked_events['loadEventEnd']['ts'] -
131 web_page_tracked_events['loadEventStart']['ts']),
132 'browser_malloc_avg': browser_malloc_sum / float(len(browser_dump_events)),
133 'browser_malloc_max': browser_malloc_max
134 }
135
136
137 def _PullMetricsFromOutputDirectory(output_directory_path):
138 """Pulls all the metrics from all the traces of a sandwich run directory.
139
140 Args:
141 output_directory_path: The sandwich run's output directory to pull the
142 metrics from.
143
144 Returns:
145 List of dictionaries with all _CSV_FIELD_NAMES's field set.
146 """
147 assert os.path.isdir(output_directory_path)
148 metrics = []
149 for node_name in os.listdir(output_directory_path):
150 if not os.path.isdir(os.path.join(output_directory_path, node_name)):
151 continue
152 try:
153 page_id = int(node_name)
154 except ValueError:
155 continue
156 trace_path = os.path.join(output_directory_path, node_name, 'trace.json')
157 if not os.path.isfile(trace_path):
158 continue
159 logging.info('processing \'%s\'' % trace_path)
160 with open(trace_path) as trace_file:
161 trace = json.load(trace_file)
162 trace_metrics = _PullMetricsFromTrace(trace)
163 trace_metrics['id'] = page_id
164 metrics.append(trace_metrics)
165 assert len(metrics) > 0, ('Looks like \'{}\' was not a sandwich ' +
166 'run directory.').format(output_directory_path)
167 return metrics
168
169
170 def main():
171 logging.basicConfig(level=logging.INFO)
172
173 parser = argparse.ArgumentParser()
174 parser.add_argument('output', type=str,
175 help='Output directory of run_sandwich.py command.')
176 args = parser.parse_args()
177
178 trace_metrics_list = _PullMetricsFromOutputDirectory(args.output)
179 trace_metrics_list.sort(key=lambda e: e['id'])
180 cs_file_path = os.path.join(args.output, 'trace_analysis.csv')
181 with open(cs_file_path, 'w') as csv_file:
182 writer = csv.DictWriter(csv_file, fieldnames=_CSV_FIELD_NAMES)
183 writer.writeheader()
184 for trace_metrics in trace_metrics_list:
185 writer.writerow(trace_metrics)
186 return 0
187
188
189 if __name__ == '__main__':
190 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/android/loading/pull_sandwich_metrics_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698