15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Jerkiness performance test for video playback. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Uses jerky tool, (http://go/jerky), to record a jerkiness metric for videos 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sensitive to jerkiness. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Jerkiness is defined as a percentage of the average on screen frame time by the 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)formula below. Where smoothed_frame_time[i] represents a frame's on screen time 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)plus amortized measurement gap error (time taken to capture each frame). 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sqrt(average((avg_frame_time - smoothed_frame_time[i])^2, i=m..n)) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)------------------------------------------------------------------ 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avg_frame_time 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Currently, only the Linux binaries are checked in for this test since we only 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)have a Linux performance bot. The current binary is a custom build with some 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fixes from veganjerky (http://go/veganjerky) for timing, waiting, and stdout 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)flushing. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TODO(dalecurtis): Move Jerky tool sources into the Chromium tree. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TODO(dalecurtis): Jerky tool uses a questionable method for determining torn 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)frames, determine if it is actually worth recording. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import glob 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import subprocess 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import tempfile 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import pyauto_media 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import pyauto 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import pyauto_utils 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# HTML test path; relative to src/chrome/test/data. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_TEST_HTML_PATH = os.path.join('media', 'html', 'media_jerky.html') 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Path under data path for test files. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_TEST_MEDIA_PATH = os.path.join('pyauto_private', 'media', 'birds') 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Path to Jerky tool executable. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_JERKY_PATH = os.path.join('pyauto_private', 'media', 'tools', 'jerky') 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Regular expression for extracting jerkiness percentage. Sample line: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# using 1:9 title 'test.log (35.36% jerky, 0 teared frames)' lw 2 with lines 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_JERKY_LOG_REGEX = re.compile( 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r'\((\d{0,3}\.?\d{0,2})% jerky, (\d+) teared frames\)') 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Regular expression for extracting computed fps. Sample line: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# INFO: 33797 us per frame => 29.6 fps. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_JERKY_LOG_FPS_REGEX = re.compile(r' => (\d+\.\d+) fps') 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Minimum and maximum number of iterations for each test. Due to timing issues 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# the jerky tool may not always calculate the fps correctly. When invalid 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# results are detected, the test is rerun up to the maxium # of times set below. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_JERKY_ITERATIONS_MIN = 3 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_JERKY_ITERATIONS_MAX = 10 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# The media files used for testing. Each entry represents a tuple of (filename, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# width, height, fps). The width and height are used to create a calibration 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# pattern for jerky tool. The fps is used to ensure Jerky tool computed a valid 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# result. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_TEST_VIDEOS = [('birds540.webm', 960, 540, 29.9)] 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetTempFilename(): 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns an absolute path to an empty temp file.""" 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f, path = tempfile.mkstemp(prefix='jerky_tmp') 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.close(f) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MediaJerkyPerfTest(pyauto.PyUITest): 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """PyAuto test container. See file doc string for more information.""" 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def StartJerkyCapture(self): 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Starts jerky tool in capture mode and waits until its ready to capture. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) A tuple of the jerky process and an absolute path to the capture log. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerky_log = GetTempFilename() 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.debug('Logging data to %s', jerky_log) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) process = subprocess.Popen( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [os.path.join(self.DataDir(), _JERKY_PATH), 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'capture', '--log', jerky_log], 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stdout=subprocess.PIPE) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Set the jerky tool process to soft-realtime w/ round-robin scheduling. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subprocess.check_call(['sudo', 'chrt', '-r', '-p', str(process.pid)]) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Wait for server to start up. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line = True 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while line: 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line = process.stdout.readline() 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if 'Waiting for calibration pattern to disappear' in line: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return process, jerky_log 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.fail('Failed to launch Jerky tool.') 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def AnalyzeJerkyCapture(self, jerky_log): 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Run jerky analyze on the specified log and return various metrics. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Once analyze has completed, the jerky_log and associated outputs will be 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removed. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerky_log: Absolute path to the capture log. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Tuple of fps, jerkiness, and torn frames. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_log_base = GetTempFilename() 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) process = subprocess.Popen( 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [os.path.join(self.DataDir(), _JERKY_PATH), 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'analyze', '--ref', jerky_log, '--out', results_log_base], 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stdout=subprocess.PIPE) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Wait for process to end w/o risking deadlock. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stdout = process.communicate()[0] 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals(process.returncode, 0) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Scrape out the calculated FPS. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fps_match = None 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for line in stdout.splitlines(): 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fps_match = _JERKY_LOG_FPS_REGEX.search(line) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if fps_match: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Open *.error.gnuplot and scrape out jerkiness. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerky_match = None 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with open('%s.error.gnuplot' % results_log_base) as results: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for line in results: 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerky_match = _JERKY_LOG_REGEX.search(line) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if jerky_match: 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Cleanup all the temp and results files jerky spits out. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for log in glob.glob('%s*' % results_log_base) + [jerky_log]: 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.unlink(log) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if fps_match and jerky_match: 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (float(fps_match.group(1)), float(jerky_match.group(1)), 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int(jerky_match.group(2))) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None, None, None 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def testMediaJerkyPerformance(self): 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Launches Jerky tool and records jerkiness for HTML5 videos. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) For each video, the test starts up jerky tool then plays until the Jerky 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tool collects enough information. Next the capture log is analyzed using 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Jerky's analyze command. If the computed fps matches the expected fps the 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerkiness metric is recorded. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) The test will run up to _JERKY_ITERATIONS_MAX times in an attempt to get at 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) least _JERKY_ITERATIONS_MIN valid values. The results are recorded under 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) the 'jerkiness' variable for graphing on the bots. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.NavigateToURL(self.GetFileURLForDataPath(_TEST_HTML_PATH)) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Xvfb on the bots is restricted to 1024x768 at present. Ensure we're using 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # all of the real estate we can. Jerky tool needs a clear picture of every 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # frame, so we can't clip the video in any way. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.SetWindowDimensions(0, 0, 1024, 768) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for name, width, height, expected_fps in _TEST_VIDEOS: 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerkiness = [] 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) torn_frames = [] 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_url = self.GetFileURLForDataPath( 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.path.join(_TEST_MEDIA_PATH, name)) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Initialize the calibration area for Jerky tool. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertTrue(self.ExecuteJavascript( 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'initializeTest(%d, %d);' % (width, height))) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runs_left = _JERKY_ITERATIONS_MIN 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runs_total = 0 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while runs_left > 0 and runs_total < _JERKY_ITERATIONS_MAX: 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runs_total += 1 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info('Running Jerky perf test #%d for %s.', runs_total, name) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Startup Jerky tool in capture mode. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerky_process, jerky_log = self.StartJerkyCapture() 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Start playback of the test video. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertTrue(self.ExecuteJavascript("startTest('%s');" % file_url)) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Wait for jerky tool to finish if it hasn't already. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertTrue(jerky_process.wait() == 0) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Stop playback of the test video so the next run can cleanly find the 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # calibration zone. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertTrue(self.ExecuteJavascript('stopTest();')) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Analyze the results. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerky_fps, jerky_percent, jerky_torn_frames = self.AnalyzeJerkyCapture( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerky_log) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (jerky_fps is None or jerky_percent is None or 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerky_torn_frames is None): 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error('No metrics recorded for this run.') 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Ensure the results for this run are valid. 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if jerky_fps != expected_fps: 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error( 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Invalid fps detected (actual: %f, expected: %f, jerkiness: %f). ' 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Discarding results for this run.', jerky_fps, expected_fps, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerky_percent) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jerkiness.append(jerky_percent) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) torn_frames.append(jerky_torn_frames) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runs_left -= 1 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pyauto_utils.PrintPerfResult('jerkiness', name, jerkiness, '%') 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__': 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pyauto_media.Main() 225