blob: 3bcd285bf5a810ac0f41c3590e3e41a8ec670c84 [file] [log] [blame]
# Copyright 2014 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.
import sys
from measurements import smooth_gesture_util
from telemetry.timeline.model import TimelineModel
from telemetry.page import page_measurement
from telemetry.page.actions import action_runner
from telemetry.web_perf import timeline_interaction_record as tir_module
from telemetry.web_perf.metrics import smoothness
RUN_SMOOTH_ACTIONS = 'RunSmoothAllActions'
class MissingDisplayFrameRateError(page_measurement.MeasurementFailure):
def __init__(self, name):
super(MissingDisplayFrameRateError, self).__init__(
'Missing display frame rate metrics: ' + name)
class SmoothnessController(object):
def __init__(self):
self._timeline_model = None
self._tracing_timeline_data = None
self._interaction = None
def Start(self, page, tab):
# FIXME: Remove webkit.console when blink.console lands in chromium and
# the ref builds are updated. crbug.com/386847
custom_categories = ['webkit.console', 'blink.console', 'benchmark']
custom_categories += page.GetSyntheticDelayCategories()
tab.browser.StartTracing(','.join(custom_categories), 60)
if tab.browser.platform.IsRawDisplayFrameRateSupported():
tab.browser.platform.StartRawDisplayFrameRateMeasurement()
# Start the smooth marker for all smooth actions.
runner = action_runner.ActionRunner(tab)
self._interaction = runner.BeginInteraction(
RUN_SMOOTH_ACTIONS, is_smooth=True)
def Stop(self, tab):
# End the smooth marker for all smooth actions.
self._interaction.End()
# Stop tracing for smoothness metric.
if tab.browser.platform.IsRawDisplayFrameRateSupported():
tab.browser.platform.StopRawDisplayFrameRateMeasurement()
self._tracing_timeline_data = tab.browser.StopTracing()
self._timeline_model = TimelineModel(
timeline_data=self._tracing_timeline_data)
def AddResults(self, tab, results):
# Add results of smoothness metric. This computes the smoothness metric for
# the time ranges of gestures, if there is at least one, else the the time
# ranges from the first action to the last action.
renderer_thread = self._timeline_model.GetRendererThreadFromTabId(
tab.id)
run_smooth_actions_record = None
smooth_records = []
for event in renderer_thread.async_slices:
if not tir_module.IsTimelineInteractionRecord(event.name):
continue
r = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
if r.logical_name == RUN_SMOOTH_ACTIONS:
assert run_smooth_actions_record is None, (
'SmoothnessController cannot issue more than 1 %s record' %
RUN_SMOOTH_ACTIONS)
run_smooth_actions_record = r
elif r.is_smooth:
smooth_records.append(
smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
self._timeline_model, r))
# If there is no other smooth records, we make measurements on time range
# marked smoothness_controller itself.
# TODO(nednguyen): when crbug.com/239179 is marked fixed, makes sure that
# page sets are responsible for issueing the markers themselves.
if len(smooth_records) == 0:
if run_smooth_actions_record is None:
sys.stderr.write('Raw tracing data:\n')
sys.stderr.write(repr(self._tracing_timeline_data.EventData()))
sys.stderr.write('\n')
raise Exception('SmoothnessController failed to issue markers for the '
'whole interaction.')
else:
smooth_records = [run_smooth_actions_record]
# Create an interaction_record for this legacy measurement. Since we don't
# wrap the results that is sent to smoothnes metric, the logical_name will
# not be used.
smoothness_metric = smoothness.SmoothnessMetric()
smoothness_metric.AddResults(
self._timeline_model, renderer_thread, smooth_records, results)
if tab.browser.platform.IsRawDisplayFrameRateSupported():
for r in tab.browser.platform.GetRawDisplayFrameRateMeasurements():
if r.value is None:
raise MissingDisplayFrameRateError(r.name)
results.Add(r.name, r.unit, r.value)
def CleanUp(self, tab):
if tab.browser.platform.IsRawDisplayFrameRateSupported():
tab.browser.platform.StopRawDisplayFrameRateMeasurement()
if tab.browser.is_tracing_running:
tab.browser.StopTracing()