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