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:
dominikg@chromium.org 2013-11-18 08:53:07 +00:00
Родитель 7f61042d64
Коммит d21af03f9f
2 изменённых файлов: 76 добавлений и 3 удалений

Просмотреть файл

@ -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()