Telemetry: Filter invalid frame lengths from SurfaceFlinger data.
We use the SurfaceFlinger data to compute the lengths of the frames (normalized to vsyncs). Sometimes the data is inconsistent and we get two frames that are less than 1 vsync apart. Filter out these frame lengths (threshold length is currently 0.5 vsyncs) and print a warning. BUG=318093 Review URL: https://codereview.chromium.org/71353006 git-svn-id: http://src.chromium.org/svn/trunk/src/build@235675 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
This commit is contained in:
Родитель
7f61042d64
Коммит
d21af03f9f
|
@ -13,6 +13,8 @@ import threading
|
|||
_SURFACE_TEXTURE_TIMESTAMPS_MESSAGE = 'SurfaceTexture update timestamps'
|
||||
_SURFACE_TEXTURE_TIMESTAMP_RE = '\d+'
|
||||
|
||||
_MIN_NORMALIZED_FRAME_LENGTH = 0.5
|
||||
|
||||
|
||||
class SurfaceStatsCollector(object):
|
||||
"""Collects surface stats for a SurfaceView from the output of SurfaceFlinger.
|
||||
|
@ -79,8 +81,11 @@ class SurfaceStatsCollector(object):
|
|||
]
|
||||
|
||||
@staticmethod
|
||||
def _GetNormalizedDeltas(data, refresh_period):
|
||||
def _GetNormalizedDeltas(data, refresh_period, min_normalized_delta=None):
|
||||
deltas = [t2 - t1 for t1, t2 in zip(data, data[1:])]
|
||||
if min_normalized_delta != None:
|
||||
deltas = filter(lambda d: d / refresh_period >= min_normalized_delta,
|
||||
deltas)
|
||||
return (deltas, [delta / refresh_period for delta in deltas])
|
||||
|
||||
@staticmethod
|
||||
|
@ -90,7 +95,13 @@ class SurfaceStatsCollector(object):
|
|||
seconds = timestamps[-1] - timestamps[0]
|
||||
|
||||
frame_lengths, normalized_frame_lengths = \
|
||||
SurfaceStatsCollector._GetNormalizedDeltas(timestamps, refresh_period)
|
||||
SurfaceStatsCollector._GetNormalizedDeltas(
|
||||
timestamps, refresh_period, _MIN_NORMALIZED_FRAME_LENGTH)
|
||||
if len(frame_lengths) < frame_count - 1:
|
||||
logging.warning('Skipping frame lengths that are too short.')
|
||||
frame_count = len(frame_lengths) + 1
|
||||
if len(frame_lengths) == 0:
|
||||
raise Exception('No valid frames lengths found.')
|
||||
length_changes, normalized_changes = \
|
||||
SurfaceStatsCollector._GetNormalizedDeltas(
|
||||
frame_lengths, refresh_period)
|
||||
|
@ -101,7 +112,7 @@ class SurfaceStatsCollector(object):
|
|||
return [
|
||||
SurfaceStatsCollector.Result(
|
||||
'avg_surface_fps' + result_suffix,
|
||||
int(round(frame_count / seconds)), 'fps'),
|
||||
int(round((frame_count - 1) / seconds)), 'fps'),
|
||||
SurfaceStatsCollector.Result(
|
||||
'jank_count' + result_suffix, jank_count, 'janks'),
|
||||
SurfaceStatsCollector.Result(
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# Copyright 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.
|
||||
|
||||
"""Unittests for SurfaceStatsCollector."""
|
||||
|
||||
import unittest
|
||||
|
||||
from surface_stats_collector import SurfaceStatsCollector
|
||||
|
||||
class TestSurfaceStatsCollector(unittest.TestCase):
|
||||
@staticmethod
|
||||
def _CreateUniformTimestamps(base, num, delta):
|
||||
return [base + i * delta for i in range(1, num + 1)]
|
||||
|
||||
@staticmethod
|
||||
def _CreateDictionaryFromResults(results):
|
||||
dictionary = {}
|
||||
for result in results:
|
||||
dictionary[result.name] = result
|
||||
return dictionary
|
||||
|
||||
def setUp(self):
|
||||
self.refresh_period = 0.1
|
||||
|
||||
def testOneFrameDelta(self):
|
||||
timestamps = self._CreateUniformTimestamps(0, 10, self.refresh_period)
|
||||
results = self._CreateDictionaryFromResults(
|
||||
SurfaceStatsCollector._CalculateResults(
|
||||
self.refresh_period, timestamps, ''))
|
||||
|
||||
self.assertEquals(results['avg_surface_fps'].value,
|
||||
int(round(1 / self.refresh_period)))
|
||||
self.assertEquals(results['jank_count'].value, 0)
|
||||
self.assertEquals(results['max_frame_delay'].value, 1)
|
||||
self.assertEquals(len(results['frame_lengths'].value), len(timestamps) - 1)
|
||||
|
||||
def testAllFramesTooShort(self):
|
||||
timestamps = self._CreateUniformTimestamps(0, 10, self.refresh_period / 100)
|
||||
self.assertRaises(Exception,
|
||||
SurfaceStatsCollector._CalculateResults,
|
||||
[self.refresh_period, timestamps, ''])
|
||||
|
||||
def testSomeFramesTooShort(self):
|
||||
timestamps = self._CreateUniformTimestamps(0, 5, self.refresh_period)
|
||||
# The following timestamps should be skipped.
|
||||
timestamps += self._CreateUniformTimestamps(timestamps[4],
|
||||
5,
|
||||
self.refresh_period / 100)
|
||||
timestamps += self._CreateUniformTimestamps(timestamps[4],
|
||||
5,
|
||||
self.refresh_period)
|
||||
|
||||
results = self._CreateDictionaryFromResults(
|
||||
SurfaceStatsCollector._CalculateResults(
|
||||
self.refresh_period, timestamps, ''))
|
||||
|
||||
self.assertEquals(len(results['frame_lengths'].value), 9)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Загрузка…
Ссылка в новой задаче