| Index: tools/perf/metrics/rendering_stats.py
|
| diff --git a/tools/perf/metrics/rendering_stats.py b/tools/perf/metrics/rendering_stats.py
|
| index 770bc65040f549b015731a4a6609cc276512e66c..6ae82b290b9fd56e945c9d3e0b753fdd256953d8 100644
|
| --- a/tools/perf/metrics/rendering_stats.py
|
| +++ b/tools/perf/metrics/rendering_stats.py
|
| @@ -4,9 +4,90 @@
|
|
|
| from operator import attrgetter
|
|
|
| +# These are LatencyInfo component names indicating the various components
|
| +# that the input event has travelled through.
|
| +# This is when the input event first reaches chrome.
|
| +UI_COMP_NAME = 'INPUT_EVENT_LATENCY_UI_COMPONENT'
|
| +# This is when the input event was originally created by OS.
|
| +ORIGINAL_COMP_NAME = 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT'
|
| +# This is when the input event was sent from browser to renderer.
|
| +BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT'
|
| +# This is when the input event has reached swap buffer.
|
| +END_COMP_NAME = 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT'
|
| +
|
| +def GetScrollInputLatencyEvents(browser_process, timeline_range):
|
| + """Get scroll events' LatencyInfo from the browser process's trace buffer
|
| + that are within the timeline_range.
|
| +
|
| + Scroll events (MouseWheel or GestureScrollUpdate) dump their LatencyInfo
|
| + into trace buffer as async trace event with name "InputLatency". The trace
|
| + event has a memeber 'step' containing its event type and a memeber 'data'
|
| + containing its latency history.
|
| +
|
| + """
|
| + mouse_wheel_events = []
|
| + touch_scroll_events = []
|
| + if not browser_process:
|
| + return (mouse_wheel_events, touch_scroll_events)
|
| + for event in browser_process.IterAllAsyncSlicesOfName("InputLatency"):
|
| + if event.start >= timeline_range.min and event.end <= timeline_range.max:
|
| + for ss in event.sub_slices:
|
| + if 'step' not in ss.args:
|
| + continue
|
| + if 'data' not in ss.args:
|
| + continue
|
| + if ss.args['step'] == 'MouseWheel':
|
| + mouse_wheel_events.append(ss)
|
| + elif ss.args['step'] == 'GestureScrollUpdate':
|
| + touch_scroll_events.append(ss)
|
| + return (mouse_wheel_events, touch_scroll_events)
|
| +
|
| +def ComputeMouseWheelScrollLatency(mouse_wheel_events):
|
| + """ Compute the mouse wheel scroll latency.
|
| +
|
| + Mouse wheel scroll latency is the time from when mouse wheel event is sent
|
| + from browser RWH to renderer (the timestamp of component
|
| + 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT') to when the scrolled page is
|
| + buffer swapped (the timestamp of component
|
| + 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT')
|
| +
|
| + """
|
| + mouse_wheel_latency = []
|
| + for event in mouse_wheel_events:
|
| + data = event.args['data']
|
| + if BEGIN_COMP_NAME in data and END_COMP_NAME in data:
|
| + latency = data[END_COMP_NAME]['time'] - data[BEGIN_COMP_NAME]['time']
|
| + mouse_wheel_latency.append(latency / 1000.0)
|
| + return mouse_wheel_latency
|
| +
|
| +def ComputeTouchScrollLatency(touch_scroll_events):
|
| + """ Compute the touch scroll latency.
|
| +
|
| + Touch scroll latency is the time from when the touch event is created to
|
| + when the scrolled page is buffer swapped.
|
| + Touch event on differnt platforms uses different LatencyInfo component to
|
| + record its creation timestamp. On Aura, the creation time is kept in
|
| + 'INPUT_EVENT_LATENCY_UI_COMPONENT' . On Android, the creation time is kept
|
| + in 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT'.
|
| +
|
| + """
|
| + touch_scroll_latency = []
|
| + for event in touch_scroll_events:
|
| + data = event.args['data']
|
| + if END_COMP_NAME in data:
|
| + end_time = data[END_COMP_NAME]['time']
|
| + if UI_COMP_NAME in data and ORIGINAL_COMP_NAME in data:
|
| + raise ValueError, 'LatencyInfo has both UI and ORIGINAL component'
|
| + if UI_COMP_NAME in data:
|
| + latency = end_time - data[UI_COMP_NAME]['time']
|
| + touch_scroll_latency.append(latency / 1000.0)
|
| + elif ORIGINAL_COMP_NAME in data:
|
| + latency = end_time - data[ORIGINAL_COMP_NAME]['time']
|
| + touch_scroll_latency.append(latency / 1000.0)
|
| + return touch_scroll_latency
|
|
|
| class RenderingStats(object):
|
| - def __init__(self, renderer_process, timeline_ranges):
|
| + def __init__(self, renderer_process, browser_process, timeline_ranges):
|
| """
|
| Utility class for extracting rendering statistics from the timeline (or
|
| other loggin facilities), and providing them in a common format to classes
|
| @@ -28,6 +109,12 @@ class RenderingStats(object):
|
| self.recorded_pixel_counts = []
|
| self.rasterize_times = []
|
| self.rasterized_pixel_counts = []
|
| + # End-to-end latency for MouseWheel scroll - from when mouse wheel event is
|
| + # generated to when the scrolled page is buffer swapped.
|
| + self.mouse_wheel_scroll_latency = []
|
| + # End-to-end latency for touch scroll event - from when the touch event is
|
| + # generated to the scrolled page is buffer swapped.
|
| + self.touch_scroll_latency = []
|
|
|
| for timeline_range in timeline_ranges:
|
| self.frame_timestamps.append([])
|
| @@ -38,11 +125,21 @@ class RenderingStats(object):
|
| self.recorded_pixel_counts.append([])
|
| self.rasterize_times.append([])
|
| self.rasterized_pixel_counts.append([])
|
| + self.mouse_wheel_scroll_latency.append([])
|
| + self.touch_scroll_latency.append([])
|
|
|
| if timeline_range.is_empty:
|
| continue
|
| self.initMainThreadStatsFromTimeline(timeline_range)
|
| self.initImplThreadStatsFromTimeline(timeline_range)
|
| + self.initScrollLatencyStatsFromTimeline(browser_process, timeline_range)
|
| +
|
| + def initScrollLatencyStatsFromTimeline(self, browser_process, timeline_range):
|
| + mouse_wheel_events, touch_scroll_events = GetScrollInputLatencyEvents(
|
| + browser_process, timeline_range)
|
| + self.mouse_wheel_scroll_latency = ComputeMouseWheelScrollLatency(
|
| + mouse_wheel_events)
|
| + self.touch_scroll_latency = ComputeTouchScrollLatency(touch_scroll_events)
|
|
|
| def initMainThreadStatsFromTimeline(self, timeline_range):
|
| event_name = 'BenchmarkInstrumentation::MainThreadRenderingStats'
|
|
|