summaryrefslogtreecommitdiffstats
path: root/tools/perf/measurements/smoothness.py
blob: 4fd0ad3401644fca0e3b78b7e6efc245c3b1bebc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# Copyright (c) 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 metrics import smoothness
from metrics.rendering_stats import RenderingStats
from telemetry.page import page_test
from telemetry.page import page_measurement


class DidNotScrollException(page_measurement.MeasurementFailure):
  def __init__(self):
    super(DidNotScrollException, self).__init__('Page did not scroll')


class MissingDisplayFrameRate(page_measurement.MeasurementFailure):
  def __init__(self, name):
    super(MissingDisplayFrameRate, self).__init__(
        'Missing display frame rate metrics: ' + name)


class NoSupportedActionException(page_measurement.MeasurementFailure):
  def __init__(self):
    super(NoSupportedActionException, self).__init__(
        'None of the actions is supported by smoothness measurement')


def GetTimelineMarkerLabelsFromAction(compound_action):
  timeline_marker_labels = []
  if not isinstance(compound_action, list):
    compound_action = [compound_action]
  for action in compound_action:
    if action.GetTimelineMarkerLabel():
      timeline_marker_labels.append(action.GetTimelineMarkerLabel())
  if not timeline_marker_labels:
    raise NoSupportedActionException()
  return timeline_marker_labels


class Smoothness(page_measurement.PageMeasurement):
  def __init__(self):
    super(Smoothness, self).__init__('smoothness')
    self._metrics = None
    self._trace_result = None

  def CustomizeBrowserOptions(self, options):
    smoothness.SmoothnessMetrics.CustomizeBrowserOptions(options)

  def CanRunForPage(self, page):
    return hasattr(page, 'smoothness')

  def WillRunAction(self, page, tab, action):
    # TODO(ermst): Remove "webkit" category after Blink r157377 is picked up by
    # the reference builds.
    tab.browser.StartTracing('webkit,webkit.console,benchmark', 60)
    if tab.browser.platform.IsRawDisplayFrameRateSupported():
      tab.browser.platform.StartRawDisplayFrameRateMeasurement()
    self._metrics = smoothness.SmoothnessMetrics(tab)
    if action.CanBeBound():
      self._metrics.BindToAction(action)
    else:
      self._metrics.Start()
      tab.ExecuteJavaScript(
          'console.time("' + smoothness.RENDER_PROCESS_MARKER + '")')

  def DidRunAction(self, page, tab, action):
    if tab.browser.platform.IsRawDisplayFrameRateSupported():
      tab.browser.platform.StopRawDisplayFrameRateMeasurement()
    if not action.CanBeBound():
      tab.ExecuteJavaScript(
          'console.timeEnd("' + smoothness.RENDER_PROCESS_MARKER + '")')
      self._metrics.Stop()
    self._trace_result = tab.browser.StopTracing()

  def MeasurePage(self, page, tab, results):
    rendering_stats_deltas = self._metrics.deltas

    # TODO(ernstm): remove numFramesSentToScreen when RenderingStats
    # cleanup CL was picked up by the reference build.
    if 'frameCount' in rendering_stats_deltas:
      frame_count = rendering_stats_deltas.get('frameCount', 0)
    else:
      frame_count = rendering_stats_deltas.get('numFramesSentToScreen', 0)

    if not (frame_count > 0):
      raise DidNotScrollException()

    timeline = self._trace_result.AsTimelineModel()
    render_process_marker = smoothness.FindTimelineMarkers(
        timeline, smoothness.RENDER_PROCESS_MARKER)
    compound_action = page_test.GetCompoundActionFromPage(
        page, self._action_name_to_run)
    timeline_marker_labels = GetTimelineMarkerLabelsFromAction(compound_action)
    # TODO(ernstm): remove try-except when the reference build was updated?
    try:
      timeline_markers = smoothness.FindTimelineMarkers(
          timeline, timeline_marker_labels)
    except smoothness.TimelineMarkerMismatchException:
      timeline_markers = render_process_marker

    benchmark_stats = RenderingStats(render_process_marker,
                                     timeline_markers,
                                     rendering_stats_deltas,
                                     self._metrics.is_using_gpu_benchmarking)
    smoothness.CalcResults(benchmark_stats, results)

    if tab.browser.platform.IsRawDisplayFrameRateSupported():
      for r in tab.browser.platform.GetRawDisplayFrameRateMeasurements():
        if r.value is None:
          raise MissingDisplayFrameRate(r.name)
        results.Add(r.name, r.unit, r.value)