| # Copyright 2013 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| from operator import attrgetter |
| |
| |
| class RenderingStats(object): |
| def __init__(self, renderer_process, timeline_markers): |
| """ |
| Utility class for extracting rendering statistics from the timeline (or |
| other loggin facilities), and providing them in a common format to classes |
| that compute benchmark metrics from this data. |
| |
| Stats can either be numbers, or lists of numbers. Classes that calculate |
| metrics from the stats must be able to handle both cases. The length of |
| different list stats may vary. |
| |
| All *_time values are measured in milliseconds. |
| """ |
| assert(len(timeline_markers) > 0) |
| self.renderer_process = renderer_process |
| |
| self.frame_timestamps = [] |
| self.frame_times = [] |
| self.paint_time = [] |
| self.painted_pixel_count = [] |
| self.record_time = [] |
| self.recorded_pixel_count = [] |
| self.rasterize_time = [] |
| self.rasterized_pixel_count = [] |
| |
| for marker in timeline_markers: |
| self.initMainThreadStatsFromTimeline(marker.start, |
| marker.start+marker.duration) |
| self.initImplThreadStatsFromTimeline(marker.start, |
| marker.start+marker.duration) |
| |
| def initMainThreadStatsFromTimeline(self, start, end): |
| event_name = 'BenchmarkInstrumentation::MainThreadRenderingStats' |
| events = [] |
| for event in self.renderer_process.IterAllSlicesOfName(event_name): |
| if event.start >= start and event.end <= end: |
| if 'data' not in event.args: |
| continue |
| events.append(event) |
| events.sort(key=attrgetter('start')) |
| |
| first_frame = True |
| for event in events: |
| frame_count = event.args['data']['frame_count'] |
| if frame_count > 1: |
| raise ValueError, 'trace contains multi-frame render stats' |
| if frame_count == 1: |
| self.frame_timestamps.append( |
| event.start) |
| if not first_frame: |
| self.frame_times.append(round(self.frame_timestamps[-1] - |
| self.frame_timestamps[-2], 2)) |
| first_frame = False |
| self.paint_time.append(1000.0 * |
| event.args['data']['paint_time']) |
| self.painted_pixel_count.append( |
| event.args['data']['painted_pixel_count']) |
| self.record_time.append(1000.0 * |
| event.args['data']['record_time']) |
| self.recorded_pixel_count.append( |
| event.args['data']['recorded_pixel_count']) |
| |
| def initImplThreadStatsFromTimeline(self, start, end): |
| event_name = 'BenchmarkInstrumentation::ImplThreadRenderingStats' |
| events = [] |
| for event in self.renderer_process.IterAllSlicesOfName(event_name): |
| if event.start >= start and event.end <= end: |
| if 'data' not in event.args: |
| continue |
| events.append(event) |
| events.sort(key=attrgetter('start')) |
| |
| first_frame = True |
| for event in events: |
| frame_count = event.args['data']['frame_count'] |
| if frame_count > 1: |
| raise ValueError, 'trace contains multi-frame render stats' |
| if frame_count == 1: |
| self.frame_timestamps.append( |
| event.start) |
| if not first_frame: |
| self.frame_times.append(round(self.frame_timestamps[-1] - |
| self.frame_timestamps[-2], 2)) |
| first_frame = False |
| self.rasterize_time.append(1000.0 * |
| event.args['data']['rasterize_time']) |
| self.rasterized_pixel_count.append( |
| event.args['data']['rasterized_pixel_count']) |