• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4import sys
5
6from measurements import smooth_gesture_util
7from telemetry.timeline.model import TimelineModel
8from telemetry.page import page_measurement
9from telemetry.page.actions import action_runner
10from telemetry.web_perf import timeline_interaction_record as tir_module
11from telemetry.web_perf.metrics import smoothness
12
13
14RUN_SMOOTH_ACTIONS = 'RunSmoothAllActions'
15
16
17class MissingDisplayFrameRateError(page_measurement.MeasurementFailure):
18  def __init__(self, name):
19    super(MissingDisplayFrameRateError, self).__init__(
20      'Missing display frame rate metrics: ' + name)
21
22class SmoothnessController(object):
23  def __init__(self):
24    self._timeline_model = None
25    self._tracing_timeline_data = None
26    self._interaction = None
27
28  def Start(self, page, tab):
29    # FIXME: Remove webkit.console when blink.console lands in chromium and
30    # the ref builds are updated. crbug.com/386847
31    custom_categories = ['webkit.console', 'blink.console', 'benchmark']
32    custom_categories += page.GetSyntheticDelayCategories()
33    tab.browser.StartTracing(','.join(custom_categories), 60)
34    if tab.browser.platform.IsRawDisplayFrameRateSupported():
35      tab.browser.platform.StartRawDisplayFrameRateMeasurement()
36    # Start the smooth marker for all smooth actions.
37    runner = action_runner.ActionRunner(tab)
38    self._interaction = runner.BeginInteraction(
39        RUN_SMOOTH_ACTIONS, is_smooth=True)
40
41  def Stop(self, tab):
42    # End the smooth marker for all smooth actions.
43    self._interaction.End()
44    # Stop tracing for smoothness metric.
45    if tab.browser.platform.IsRawDisplayFrameRateSupported():
46      tab.browser.platform.StopRawDisplayFrameRateMeasurement()
47    self._tracing_timeline_data = tab.browser.StopTracing()
48    self._timeline_model = TimelineModel(
49      timeline_data=self._tracing_timeline_data)
50
51  def AddResults(self, tab, results):
52    # Add results of smoothness metric. This computes the smoothness metric for
53    # the time ranges of gestures, if there is at least one, else the the time
54    # ranges from the first action to the last action.
55
56    renderer_thread = self._timeline_model.GetRendererThreadFromTabId(
57        tab.id)
58    run_smooth_actions_record = None
59    smooth_records = []
60    for event in renderer_thread.async_slices:
61      if not tir_module.IsTimelineInteractionRecord(event.name):
62        continue
63      r = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
64      if r.logical_name == RUN_SMOOTH_ACTIONS:
65        assert run_smooth_actions_record is None, (
66          'SmoothnessController cannot issue more than 1 %s record' %
67          RUN_SMOOTH_ACTIONS)
68        run_smooth_actions_record = r
69      elif r.is_smooth:
70        smooth_records.append(
71          smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
72            self._timeline_model, r))
73
74    # If there is no other smooth records, we make measurements on time range
75    # marked smoothness_controller itself.
76    # TODO(nednguyen): when crbug.com/239179 is marked fixed, makes sure that
77    # page sets are responsible for issueing the markers themselves.
78    if len(smooth_records) == 0:
79      if run_smooth_actions_record is None:
80        sys.stderr.write('Raw tracing data:\n')
81        sys.stderr.write(repr(self._tracing_timeline_data.EventData()))
82        sys.stderr.write('\n')
83        raise Exception('SmoothnessController failed to issue markers for the '
84                        'whole interaction.')
85      else:
86        smooth_records = [run_smooth_actions_record]
87
88    # Create an interaction_record for this legacy measurement. Since we don't
89    # wrap the results that is sent to smoothnes metric, the logical_name will
90    # not be used.
91    smoothness_metric = smoothness.SmoothnessMetric()
92    smoothness_metric.AddResults(
93      self._timeline_model, renderer_thread, smooth_records, results)
94    if tab.browser.platform.IsRawDisplayFrameRateSupported():
95      for r in tab.browser.platform.GetRawDisplayFrameRateMeasurements():
96        if r.value is None:
97          raise MissingDisplayFrameRateError(r.name)
98        results.Add(r.name, r.unit, r.value)
99
100  def CleanUp(self, tab):
101    if tab.browser.platform.IsRawDisplayFrameRateSupported():
102      tab.browser.platform.StopRawDisplayFrameRateMeasurement()
103    if tab.browser.is_tracing_running:
104      tab.browser.StopTracing()
105