diff --git a/android/pylib/perf/surface_stats_collector.py b/android/pylib/perf/surface_stats_collector.py index c38b1b417..9d92b4376 100644 --- a/android/pylib/perf/surface_stats_collector.py +++ b/android/pylib/perf/surface_stats_collector.py @@ -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( diff --git a/android/pylib/perf/surface_stats_collector_unittest.py b/android/pylib/perf/surface_stats_collector_unittest.py new file mode 100644 index 000000000..982b55ddf --- /dev/null +++ b/android/pylib/perf/surface_stats_collector_unittest.py @@ -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()