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

Side by Side Diff: tools/telemetry/telemetry/web_perf/metrics/smoothness.py

Issue 765773004: telemetry: Clean up SurfaceFlinger statistics (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: clean-up Created 6 years 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 unified diff | Download patch
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import logging
5 from telemetry.perf_tests_helper import FlattenList 6 from telemetry.perf_tests_helper import FlattenList
6 from telemetry.util import statistics 7 from telemetry.util import statistics
7 from telemetry.value import list_of_scalar_values 8 from telemetry.value import list_of_scalar_values
8 from telemetry.value import scalar 9 from telemetry.value import scalar
9 from telemetry.web_perf.metrics import rendering_stats 10 from telemetry.web_perf.metrics import rendering_stats
10 from telemetry.web_perf.metrics import timeline_based_metric 11 from telemetry.web_perf.metrics import timeline_based_metric
11 12
12 13
13 NOT_ENOUGH_FRAMES_MESSAGE = ( 14 NOT_ENOUGH_FRAMES_MESSAGE = (
14 'Not enough frames for smoothness metrics (at least two are required).\n' 15 'Not enough frames for smoothness metrics (at least two are required).\n'
(...skipping 27 matching lines...) Expand all
42 None value for the queueing duration metric. 43 None value for the queueing duration metric.
43 """ 44 """
44 45
45 def __init__(self): 46 def __init__(self):
46 super(SmoothnessMetric, self).__init__() 47 super(SmoothnessMetric, self).__init__()
47 48
48 def AddResults(self, model, renderer_thread, interaction_records, results): 49 def AddResults(self, model, renderer_thread, interaction_records, results):
49 self.VerifyNonOverlappedRecords(interaction_records) 50 self.VerifyNonOverlappedRecords(interaction_records)
50 renderer_process = renderer_thread.parent 51 renderer_process = renderer_thread.parent
51 stats = rendering_stats.RenderingStats( 52 stats = rendering_stats.RenderingStats(
52 renderer_process, model.browser_process, 53 renderer_process, model.browser_process, model.surface_flinger_process,
53 [r.GetBounds() for r in interaction_records]) 54 [r.GetBounds() for r in interaction_records])
54 self._PopulateResultsFromStats(results, stats) 55 has_surface_flinger_stats = model.surface_flinger_process is not None
56 self._PopulateResultsFromStats(results, stats, has_surface_flinger_stats)
55 57
56 def _PopulateResultsFromStats(self, results, stats): 58 def _PopulateResultsFromStats(self, results, stats,
59 has_surface_flinger_stats):
57 page = results.current_page 60 page = results.current_page
58 values = [ 61 values = [
59 self._ComputeQueueingDuration(page, stats), 62 self._ComputeQueueingDuration(page, stats),
60 self._ComputeFrameTimeDiscrepancy(page, stats), 63 self._ComputeFrameTimeDiscrepancy(page, stats),
61 self._ComputeMeanPixelsApproximated(page, stats) 64 self._ComputeMeanPixelsApproximated(page, stats)
62 ] 65 ]
63 values += self._ComputeLatencyMetric(page, stats, 'input_event_latency', 66 values += self._ComputeLatencyMetric(page, stats, 'input_event_latency',
64 stats.input_event_latency) 67 stats.input_event_latency)
65 values += self._ComputeLatencyMetric(page, stats, 'scroll_update_latency', 68 values += self._ComputeLatencyMetric(page, stats, 'scroll_update_latency',
66 stats.scroll_update_latency) 69 stats.scroll_update_latency)
67 values += self._ComputeFirstGestureScrollUpdateLatency(page, stats) 70 values += self._ComputeFirstGestureScrollUpdateLatency(page, stats)
68 values += self._ComputeFrameTimeMetric(page, stats) 71 values += self._ComputeFrameTimeMetric(page, stats)
72 if has_surface_flinger_stats:
73 values += self._ComputeSurfaceFlingerMetric(page, stats)
74
69 for v in values: 75 for v in values:
70 results.AddValue(v) 76 results.AddValue(v)
71 77
72 def _HasEnoughFrames(self, list_of_frame_timestamp_lists): 78 def _HasEnoughFrames(self, list_of_frame_timestamp_lists):
73 """Whether we have collected at least two frames in every timestamp list.""" 79 """Whether we have collected at least two frames in every timestamp list."""
74 return all(len(s) >= 2 for s in list_of_frame_timestamp_lists) 80 return all(len(s) >= 2 for s in list_of_frame_timestamp_lists)
75 81
82 @staticmethod
83 def _GetNormalizedDeltas(data, refresh_period, min_normalized_delta=None):
84 deltas = [t2 - t1 for t1, t2 in zip(data, data[1:])]
85 if min_normalized_delta != None:
86 deltas = [d for d in deltas
87 if d / refresh_period >= min_normalized_delta]
88 return (deltas, [delta / refresh_period for delta in deltas])
89
90 def _ComputeSurfaceFlingerMetric(self, page, stats):
91 jank_count = None
92 avg_surface_fps = None
93 max_frame_delay = None
94 frame_lengths = None
95 none_value_reason = None
96 if self._HasEnoughFrames(stats.frame_timestamps):
97 timestamps = FlattenList(stats.frame_timestamps)
98 frame_count = len(timestamps)
99 milliseconds = timestamps[-1] - timestamps[0]
100 min_normalized_frame_length = 0.5
101
102 frame_lengths, normalized_frame_lengths = \
103 self._GetNormalizedDeltas(timestamps, stats.refresh_period,
104 min_normalized_frame_length)
105 if len(frame_lengths) < frame_count - 1:
106 logging.warning('Skipping frame lengths that are too short.')
107 frame_count = len(frame_lengths) + 1
108 if len(frame_lengths) == 0:
109 raise Exception('No valid frames lengths found.')
110 _, normalized_changes = \
111 self._GetNormalizedDeltas(frame_lengths, stats.refresh_period)
112 jankiness = [max(0, round(change)) for change in normalized_changes]
113 pause_threshold = 20
114 jank_count = sum(1 for change in jankiness
115 if change > 0 and change < pause_threshold)
116 avg_surface_fps = int(round((frame_count - 1) * 1000.0 / milliseconds))
117 max_frame_delay = round(max(normalized_frame_lengths))
118 frame_lengths = normalized_frame_lengths
119 else:
120 none_value_reason = NOT_ENOUGH_FRAMES_MESSAGE
121
122 return (
123 scalar.ScalarValue(
124 page, 'avg_surface_fps', 'fps', avg_surface_fps,
125 description='Average frames per second as measured by the '
126 'platform\'s SurfaceFlinger.',
127 none_value_reason=none_value_reason),
128 scalar.ScalarValue(
129 page, 'jank_count', 'janks', jank_count,
130 description='Number of changes in frame rate as measured by the '
131 'platform\'s SurfaceFlinger.',
132 none_value_reason=none_value_reason),
133 scalar.ScalarValue(
134 page, 'max_frame_delay', 'vsyncs', max_frame_delay,
135 description='Largest frame time as measured by the platform\'s '
136 'SurfaceFlinger.',
137 none_value_reason=none_value_reason),
138 list_of_scalar_values.ListOfScalarValues(
139 page, 'frame_lengths', 'vsyncs', frame_lengths,
140 description='Frame time in vsyncs as measured by the platform\'s '
141 'SurfaceFlinger.',
142 none_value_reason=none_value_reason)
143 )
144
76 def _ComputeLatencyMetric(self, page, stats, name, list_of_latency_lists): 145 def _ComputeLatencyMetric(self, page, stats, name, list_of_latency_lists):
77 """Returns Values for the mean and discrepancy for given latency stats.""" 146 """Returns Values for the mean and discrepancy for given latency stats."""
78 mean_latency = None 147 mean_latency = None
79 latency_discrepancy = None 148 latency_discrepancy = None
80 none_value_reason = None 149 none_value_reason = None
81 if self._HasEnoughFrames(stats.frame_timestamps): 150 if self._HasEnoughFrames(stats.frame_timestamps):
82 latency_list = FlattenList(list_of_latency_lists) 151 latency_list = FlattenList(list_of_latency_lists)
83 if len(latency_list) == 0: 152 if len(latency_list) == 0:
84 return () 153 return ()
85 mean_latency = round(statistics.ArithmeticMean(latency_list), 3) 154 mean_latency = round(statistics.ArithmeticMean(latency_list), 3)
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 if self._HasEnoughFrames(stats.frame_timestamps): 279 if self._HasEnoughFrames(stats.frame_timestamps):
211 mean_pixels_approximated = round(statistics.ArithmeticMean( 280 mean_pixels_approximated = round(statistics.ArithmeticMean(
212 FlattenList(stats.approximated_pixel_percentages)), 3) 281 FlattenList(stats.approximated_pixel_percentages)), 3)
213 else: 282 else:
214 none_value_reason = NOT_ENOUGH_FRAMES_MESSAGE 283 none_value_reason = NOT_ENOUGH_FRAMES_MESSAGE
215 return scalar.ScalarValue( 284 return scalar.ScalarValue(
216 page, 'mean_pixels_approximated', 'percent', mean_pixels_approximated, 285 page, 'mean_pixels_approximated', 'percent', mean_pixels_approximated,
217 description='Percentage of pixels that were approximated ' 286 description='Percentage of pixels that were approximated '
218 '(checkerboarding, low-resolution tiles, etc.).', 287 '(checkerboarding, low-resolution tiles, etc.).',
219 none_value_reason=none_value_reason) 288 none_value_reason=none_value_reason)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698