OLD | NEW |
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Pull a sandwich run's output directory's metrics from traces into a CSV. | 5 """Pull a sandwich run's output directory's metrics from traces into a CSV. |
6 | 6 |
7 python pull_sandwich_metrics.py -h | 7 python pull_sandwich_metrics.py -h |
8 """ | 8 """ |
9 | 9 |
10 import collections | 10 import collections |
(...skipping 14 matching lines...) Expand all Loading... |
25 from telemetry.internal.image_processing import video | 25 from telemetry.internal.image_processing import video |
26 from telemetry.util import image_util | 26 from telemetry.util import image_util |
27 from telemetry.util import rgba_color | 27 from telemetry.util import rgba_color |
28 | 28 |
29 import loading_trace as loading_trace_module | 29 import loading_trace as loading_trace_module |
30 import sandwich_runner | 30 import sandwich_runner |
31 import sandwich_misc | 31 import sandwich_misc |
32 import tracing | 32 import tracing |
33 | 33 |
34 | 34 |
35 CSV_FIELD_NAMES = [ | 35 COMMON_CSV_COLUMN_NAMES = [ |
36 'repeat_id', | |
37 'url', | |
38 'chromium_commit', | 36 'chromium_commit', |
39 'platform', | 37 'platform', |
40 'subresource_discoverer', | |
41 'subresource_count', | |
42 # The amount of subresources detected at SetupBenchmark step. | |
43 'subresource_count_theoretic', | |
44 # Amount of subresources for caching as suggested by the subresource | |
45 # discoverer. | |
46 'cached_subresource_count_theoretic', | |
47 'cached_subresource_count', | |
48 'first_layout', | 38 'first_layout', |
49 'first_contentful_paint', | 39 'first_contentful_paint', |
50 'total_load', | 40 'total_load', |
51 'js_onload_event', | 41 'js_onload_event', |
52 'browser_malloc_avg', | 42 'browser_malloc_avg', |
53 'browser_malloc_max', | 43 'browser_malloc_max', |
54 'speed_index', | 44 'speed_index', |
55 'net_emul.name', # Should be in emulation.NETWORK_CONDITIONS.keys() | 45 'net_emul.name', # Should be in emulation.NETWORK_CONDITIONS.keys() |
56 'net_emul.download', | 46 'net_emul.download', |
57 'net_emul.upload', | 47 'net_emul.upload', |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 assert attr['units'] == 'bytes' | 192 assert attr['units'] == 'bytes' |
203 size = int(attr['value'], 16) | 193 size = int(attr['value'], 16) |
204 browser_malloc_sum += size | 194 browser_malloc_sum += size |
205 browser_malloc_max = max(browser_malloc_max, size) | 195 browser_malloc_max = max(browser_malloc_max, size) |
206 return { | 196 return { |
207 'browser_malloc_avg': browser_malloc_sum / float(len(browser_dump_events)), | 197 'browser_malloc_avg': browser_malloc_sum / float(len(browser_dump_events)), |
208 'browser_malloc_max': browser_malloc_max | 198 'browser_malloc_max': browser_malloc_max |
209 } | 199 } |
210 | 200 |
211 | 201 |
212 def _ExtractBenchmarkStatistics(benchmark_setup, loading_trace): | |
213 """Extracts some useful statistics from a benchmark run. | |
214 | |
215 Args: | |
216 benchmark_setup: benchmark_setup: dict representing the benchmark setup | |
217 JSON. The JSON format is according to: | |
218 PrefetchBenchmarkBuilder.PopulateLoadBenchmark.SetupBenchmark. | |
219 loading_trace: loading_trace_module.LoadingTrace. | |
220 | |
221 Returns: | |
222 Dictionary with all extracted fields set. | |
223 """ | |
224 return { | |
225 'subresource_discoverer': benchmark_setup['subresource_discoverer'], | |
226 'subresource_count': len(sandwich_misc.ListUrlRequests( | |
227 loading_trace, sandwich_misc.RequestOutcome.All)), | |
228 'subresource_count_theoretic': len(benchmark_setup['url_resources']), | |
229 'cached_subresource_count': len(sandwich_misc.ListUrlRequests( | |
230 loading_trace, sandwich_misc.RequestOutcome.ServedFromCache)), | |
231 'cached_subresource_count_theoretic': | |
232 len(benchmark_setup['cache_whitelist']), | |
233 } | |
234 | |
235 | |
236 def _ExtractCompletenessRecordFromVideo(video_path): | 202 def _ExtractCompletenessRecordFromVideo(video_path): |
237 """Extracts the completeness record from a video. | 203 """Extracts the completeness record from a video. |
238 | 204 |
239 The video must start with a filled rectangle of orange (RGB: 222, 100, 13), to | 205 The video must start with a filled rectangle of orange (RGB: 222, 100, 13), to |
240 give the view-port size/location from where to compute the completeness. | 206 give the view-port size/location from where to compute the completeness. |
241 | 207 |
242 Args: | 208 Args: |
243 video_path: Path of the video to extract the completeness list from. | 209 video_path: Path of the video to extract the completeness list from. |
244 | 210 |
245 Returns: | 211 Returns: |
(...skipping 17 matching lines...) Expand all Loading... |
263 if total_distance == 0: | 229 if total_distance == 0: |
264 if histogram.Distance(final_histogram) == 0: | 230 if histogram.Distance(final_histogram) == 0: |
265 return 1.0 | 231 return 1.0 |
266 else: | 232 else: |
267 return 0.0 | 233 return 0.0 |
268 return 1 - histogram.Distance(final_histogram) / total_distance | 234 return 1 - histogram.Distance(final_histogram) / total_distance |
269 | 235 |
270 return [(time, FrameProgress(hist)) for time, hist in histograms] | 236 return [(time, FrameProgress(hist)) for time, hist in histograms] |
271 | 237 |
272 | 238 |
273 def ComputeSpeedIndex(completeness_record): | 239 def _ComputeSpeedIndex(completeness_record): |
274 """Computes the speed-index from a completeness record. | 240 """Computes the speed-index from a completeness record. |
275 | 241 |
276 Args: | 242 Args: |
277 completeness_record: list(CompletenessPoint) | 243 completeness_record: list(CompletenessPoint) |
278 | 244 |
279 Returns: | 245 Returns: |
280 Speed-index value. | 246 Speed-index value. |
281 """ | 247 """ |
282 speed_index = 0.0 | 248 speed_index = 0.0 |
283 last_time = completeness_record[0][0] | 249 last_time = completeness_record[0][0] |
284 last_completness = completeness_record[0][1] | 250 last_completness = completeness_record[0][1] |
285 for time, completeness in completeness_record: | 251 for time, completeness in completeness_record: |
286 if time < last_time: | 252 if time < last_time: |
287 raise ValueError('Completeness record must be sorted by timestamps.') | 253 raise ValueError('Completeness record must be sorted by timestamps.') |
288 elapsed = time - last_time | 254 elapsed = time - last_time |
289 speed_index += elapsed * (1.0 - last_completness) | 255 speed_index += elapsed * (1.0 - last_completness) |
290 last_time = time | 256 last_time = time |
291 last_completness = completeness | 257 last_completness = completeness |
292 return speed_index | 258 return speed_index |
293 | 259 |
294 | 260 |
295 def _ExtractMetricsFromRunDirectory(benchmark_setup, run_directory_path): | 261 def ExtractCommonMetricsFromRepeatDirectory(repeat_dir, trace): |
296 """Extracts all the metrics from traces and video of a sandwich run. | 262 """Extracts all the metrics from traces and video of a sandwich run repeat |
| 263 directory. |
297 | 264 |
298 Args: | 265 Args: |
299 benchmark_setup: benchmark_setup: dict representing the benchmark setup | 266 repeat_dir: Path of the repeat directory within a run directory. |
300 JSON. The JSON format is according to: | 267 trace: preloaded LoadingTrace in |repeat_dir| |
301 PrefetchBenchmarkBuilder.PopulateLoadBenchmark.SetupBenchmark. | 268 |
302 run_directory_path: Path of the run directory. | 269 Contract: |
| 270 trace == LoadingTrace.FromJsonFile( |
| 271 os.path.join(repeat_dir, sandwich_runner.TRACE_FILENAME)) |
303 | 272 |
304 Returns: | 273 Returns: |
305 Dictionary of extracted metrics. | 274 Dictionary of extracted metrics. |
306 """ | 275 """ |
307 trace_path = os.path.join(run_directory_path, 'trace.json') | |
308 logging.info('processing trace \'%s\'' % trace_path) | |
309 loading_trace = loading_trace_module.LoadingTrace.FromJsonFile(trace_path) | |
310 run_metrics = { | 276 run_metrics = { |
311 'url': loading_trace.url, | 277 'chromium_commit': trace.metadata['chromium_commit'], |
312 'chromium_commit': loading_trace.metadata['chromium_commit'], | 278 'platform': (trace.metadata['platform']['os'] + '-' + |
313 'platform': (loading_trace.metadata['platform']['os'] + '-' + | 279 trace.metadata['platform']['product_model']) |
314 loading_trace.metadata['platform']['product_model']) | |
315 } | 280 } |
316 run_metrics.update(_ExtractDefaultMetrics(loading_trace)) | 281 run_metrics.update(_ExtractDefaultMetrics(trace)) |
317 run_metrics.update(_ExtractMemoryMetrics(loading_trace)) | 282 run_metrics.update(_ExtractMemoryMetrics(trace)) |
318 if benchmark_setup: | 283 video_path = os.path.join(repeat_dir, sandwich_runner.VIDEO_FILENAME) |
319 run_metrics.update( | |
320 _ExtractBenchmarkStatistics(benchmark_setup, loading_trace)) | |
321 video_path = os.path.join(run_directory_path, 'video.mp4') | |
322 if os.path.isfile(video_path): | 284 if os.path.isfile(video_path): |
323 logging.info('processing speed-index video \'%s\'' % video_path) | 285 logging.info('processing speed-index video \'%s\'' % video_path) |
324 try: | 286 try: |
325 completeness_record = _ExtractCompletenessRecordFromVideo(video_path) | 287 completeness_record = _ExtractCompletenessRecordFromVideo(video_path) |
326 run_metrics['speed_index'] = ComputeSpeedIndex(completeness_record) | 288 run_metrics['speed_index'] = _ComputeSpeedIndex(completeness_record) |
327 except video.BoundingBoxNotFoundException: | 289 except video.BoundingBoxNotFoundException: |
328 # Sometimes the bounding box for the web content area is not present. Skip | 290 # Sometimes the bounding box for the web content area is not present. Skip |
329 # calculating Speed Index. | 291 # calculating Speed Index. |
330 run_metrics['speed_index'] = _FAILED_CSV_VALUE | 292 run_metrics['speed_index'] = _FAILED_CSV_VALUE |
331 else: | 293 else: |
332 run_metrics['speed_index'] = _UNAVAILABLE_CSV_VALUE | 294 run_metrics['speed_index'] = _UNAVAILABLE_CSV_VALUE |
333 for key, value in loading_trace.metadata['network_emulation'].iteritems(): | 295 for key, value in trace.metadata['network_emulation'].iteritems(): |
334 run_metrics['net_emul.' + key] = value | 296 run_metrics['net_emul.' + key] = value |
| 297 assert set(run_metrics.keys()) == set(COMMON_CSV_COLUMN_NAMES) |
335 return run_metrics | 298 return run_metrics |
336 | |
337 | |
338 def ExtractMetricsFromRunnerOutputDirectory(benchmark_setup_path, | |
339 output_directory_path): | |
340 """Extracts all the metrics from all the traces of a sandwich runner output | |
341 directory. | |
342 | |
343 Args: | |
344 benchmark_setup_path: Path of the JSON of the benchmark setup. | |
345 output_directory_path: The sandwich runner's output directory to extract the | |
346 metrics from. | |
347 | |
348 Returns: | |
349 List of dictionaries. | |
350 """ | |
351 benchmark_setup = None | |
352 if benchmark_setup_path: | |
353 benchmark_setup = json.load(open(benchmark_setup_path)) | |
354 assert os.path.isdir(output_directory_path) | |
355 metrics = [] | |
356 for node_name in os.listdir(output_directory_path): | |
357 if not os.path.isdir(os.path.join(output_directory_path, node_name)): | |
358 continue | |
359 try: | |
360 repeat_id = int(node_name) | |
361 except ValueError: | |
362 continue | |
363 run_directory_path = os.path.join(output_directory_path, node_name) | |
364 run_metrics = _ExtractMetricsFromRunDirectory( | |
365 benchmark_setup, run_directory_path) | |
366 run_metrics['repeat_id'] = repeat_id | |
367 # TODO(gabadie): Make common metrics extraction with benchmark type | |
368 # specific CSV column. | |
369 # assert set(run_metrics.keys()) == set(CSV_FIELD_NAMES) | |
370 metrics.append(run_metrics) | |
371 assert len(metrics) > 0, ('Looks like \'{}\' was not a sandwich runner ' + | |
372 'output directory.').format(output_directory_path) | |
373 return metrics | |
OLD | NEW |