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

Unified Diff: tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py

Issue 397663002: Addition of first_gesture_scroll_latency (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Renaming of new metric Created 6 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py
diff --git a/tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py b/tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py
index bd8c826d440c907e5b6e18975665143056d3d62f..fc9903249f76f40ae4f5ef7503992e4027245635 100644
--- a/tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py
+++ b/tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py
@@ -6,6 +6,7 @@ import logging
from operator import attrgetter
from telemetry.page import page_measurement
from telemetry.web_perf.metrics import rendering_frame
+from collections import namedtuple
# These are LatencyInfo component names indicating the various components
# that the input event has travelled through.
@@ -17,7 +18,12 @@ ORIGINAL_COMP_NAME = 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT'
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'
+# The 'step' for an event that is a gesture scroll update
+GESTURE_SCROLL_UPDATE = 'GestureScrollUpdate'
+# Wildcard used to match all step types
+ALL_INPUT_EVENTS = ''
+InputEventDetails = namedtuple('InputEventDetails','start_time latency')
class NotEnoughFramesError(page_measurement.MeasurementFailure):
def __init__(self, frame_count):
@@ -31,7 +37,6 @@ class NotEnoughFramesError(page_measurement.MeasurementFailure):
'- Pages that render extremely slow\n' +
'- Pages that can\'t be scrolled')
-
def GetInputLatencyEvents(process, timeline_range):
"""Get input events' LatencyInfo from the process's trace buffer that are
within the timeline_range.
@@ -41,47 +46,114 @@ def GetInputLatencyEvents(process, timeline_range):
its latency history.
"""
+
input_events = []
if not process:
return input_events
for event in process.IterAllAsyncSlicesOfName('InputLatency'):
+
if event.start >= timeline_range.min and event.end <= timeline_range.max:
for ss in event.sub_slices:
if 'data' in ss.args:
input_events.append(ss)
+
return input_events
+def FindInputEventStartAndEnd(event):
+ """
+ Input event on different platforms uses different LatencyInfo component to
+ record its creation timestamp. We go through the following component list
+ to find the creation timestamp:
+ 1. INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT -- when event is created in OS
+ 2. INPUT_EVENT_LATENCY_UI_COMPONENT -- when event reaches Chrome
+ 3. INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT -- when event reaches RenderWidget
+ """
+
+ data = event.args['data']
+
+ if END_COMP_NAME in data:
+ end_time = data[END_COMP_NAME]['time']
+ if ORIGINAL_COMP_NAME in data:
+ start_time = data[ORIGINAL_COMP_NAME]['time']
+ elif UI_COMP_NAME in data:
+ start_time = data[UI_COMP_NAME]['time']
+ elif BEGIN_COMP_NAME in data:
+ start_time = data[BEGIN_COMP_NAME]['time']
+ else:
+ raise ValueError, 'LatencyInfo has no begin component'
+
+ # Events are stored internal in microseconds, convert to ms
+
+ start_time_ms = start_time / 1000.0
+ end_time_ms = end_time / 1000.0
+
+ return True, start_time_ms, end_time_ms
+
+ # Return failure and dummy values
+ return False, 0, 0
+
+
def ComputeInputEventLatency(input_events):
""" Compute the input event latency.
Input event latency is the time from when the input event is created to
when its resulted page is swap buffered.
- Input event on differnt platforms uses different LatencyInfo component to
- record its creation timestamp. We go through the following component list
- to find the creation timestamp:
- 1. INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT -- when event is created in OS
- 2. INPUT_EVENT_LATENCY_UI_COMPONENT -- when event reaches Chrome
- 3. INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT -- when event reaches RenderWidget
-
"""
input_event_latency = []
for event in input_events:
- data = event.args['data']
- if END_COMP_NAME in data:
- end_time = data[END_COMP_NAME]['time']
- if ORIGINAL_COMP_NAME in data:
- latency = end_time - data[ORIGINAL_COMP_NAME]['time']
- elif UI_COMP_NAME in data:
- latency = end_time - data[UI_COMP_NAME]['time']
- elif BEGIN_COMP_NAME in data:
- latency = end_time - data[BEGIN_COMP_NAME]['time']
- else:
- raise ValueError, 'LatencyInfo has no begin component'
- input_event_latency.append(latency / 1000.0)
+
+ event_exists, start_time, end_time = FindInputEventStartAndEnd(event)
+
+ if event_exists:
+ latency = end_time - start_time
+ input_event_latency.append(latency)
+
return input_event_latency
+def EventIsOfDesireType(event, requested_type):
+ """ Given an event and a type, return True if the event is of the requested
+ type. A wildcard 'ALL_INPUT_EVENTS' can be used if we want to match
+ all events.
+ """
+ if requested_type == ALL_INPUT_EVENTS:
+ return True
+
+ if not 'step' in event.args:
+ # We don't know what type of event this is, assume its wrong
+ return False
+
+ if requested_type == event.args['step']:
+ # These are the events we're looking for
+ return True
+
+ return False
+
+
+def GetInputEventStartAndLatency(input_events, requested_type):
+ """ Generate an array of events of the requested type. Each event contains
+ the event start time and its latency (i.e. how long it took to be
+ serviced).
+ """
+ start_and_latency = []
+ for event in input_events:
+
+ if not EventIsOfDesireType(event, requested_type):
+ continue
+
+ event_exists, start_time, end_time = FindInputEventStartAndEnd(event)
+
+ if event_exists:
+
+ latency = end_time - start_time
+ event_details = InputEventDetails(start_time, latency)
+ start_and_latency.append(event_details)
+
+ return start_and_latency
+
+
+
def HasRenderingStats(process):
""" Returns True if the process contains at least one
BenchmarkInstrumentation::*RenderingStats event with a frame.
@@ -130,6 +202,7 @@ class RenderingStats(object):
# End-to-end latency for input event - from when input event is
# generated to when the its resulted page is swap buffered.
self.input_event_latency = []
+ self.input_start_and_latency_GSU = []
self.frame_queueing_durations = []
for timeline_range in timeline_ranges:
@@ -143,6 +216,7 @@ class RenderingStats(object):
self.rasterized_pixel_counts.append([])
self.approximated_pixel_percentages.append([])
self.input_event_latency.append([])
+ self.input_start_and_latency_GSU.append([])
if timeline_range.is_empty:
continue
@@ -170,6 +244,10 @@ class RenderingStats(object):
timeline_range))
self.input_event_latency[-1] = ComputeInputEventLatency(latency_events)
+ self.input_start_and_latency_GSU[-1] = GetInputEventStartAndLatency(
+ latency_events,
+ GESTURE_SCROLL_UPDATE)
+
def _GatherEvents(self, event_name, process, timeline_range):
events = []
for event in process.IterAllSlicesOfName(event_name):

Powered by Google App Engine
This is Rietveld 408576698