1*c8dee2aaSAndroid Build Coastguard Worker#!/usr/bin/env python 2*c8dee2aaSAndroid Build Coastguard Worker 3*c8dee2aaSAndroid Build Coastguard Worker# Copyright 2016 Google Inc. 4*c8dee2aaSAndroid Build Coastguard Worker# 5*c8dee2aaSAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 6*c8dee2aaSAndroid Build Coastguard Worker# found in the LICENSE file. 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Workerfrom __future__ import print_function 9*c8dee2aaSAndroid Build Coastguard Workerfrom _adb import Adb 10*c8dee2aaSAndroid Build Coastguard Workerfrom _benchresult import BenchResult 11*c8dee2aaSAndroid Build Coastguard Workerfrom _hardware import HardwareException, Hardware 12*c8dee2aaSAndroid Build Coastguard Workerfrom argparse import ArgumentParser 13*c8dee2aaSAndroid Build Coastguard Workerfrom multiprocessing import Queue 14*c8dee2aaSAndroid Build Coastguard Workerfrom threading import Thread, Timer 15*c8dee2aaSAndroid Build Coastguard Workerimport collections 16*c8dee2aaSAndroid Build Coastguard Workerimport glob 17*c8dee2aaSAndroid Build Coastguard Workerimport math 18*c8dee2aaSAndroid Build Coastguard Workerimport re 19*c8dee2aaSAndroid Build Coastguard Workerimport subprocess 20*c8dee2aaSAndroid Build Coastguard Workerimport sys 21*c8dee2aaSAndroid Build Coastguard Workerimport time 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Worker__argparse = ArgumentParser(description=""" 24*c8dee2aaSAndroid Build Coastguard Worker 25*c8dee2aaSAndroid Build Coastguard WorkerExecutes the skpbench binary with various configs and skps. 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard WorkerAlso monitors the output in order to filter out and re-run results that have an 28*c8dee2aaSAndroid Build Coastguard Workerunacceptable stddev. 29*c8dee2aaSAndroid Build Coastguard Worker 30*c8dee2aaSAndroid Build Coastguard Worker""") 31*c8dee2aaSAndroid Build Coastguard Worker 32*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('skpbench', 33*c8dee2aaSAndroid Build Coastguard Worker help="path to the skpbench binary") 34*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--adb', 35*c8dee2aaSAndroid Build Coastguard Worker action='store_true', help="execute skpbench over adb") 36*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--adb_binary', default='adb', 37*c8dee2aaSAndroid Build Coastguard Worker help="The name of the adb binary to use.") 38*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('-s', '--device-serial', 39*c8dee2aaSAndroid Build Coastguard Worker help="if using adb, ID of the specific device to target " 40*c8dee2aaSAndroid Build Coastguard Worker "(only required if more than 1 device is attached)") 41*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('-m', '--max-stddev', 42*c8dee2aaSAndroid Build Coastguard Worker type=float, default=4, 43*c8dee2aaSAndroid Build Coastguard Worker help="initial max allowable relative standard deviation") 44*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('-x', '--suffix', 45*c8dee2aaSAndroid Build Coastguard Worker help="suffix to append on config (e.g. '_before', '_after')") 46*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('-w','--write-path', 47*c8dee2aaSAndroid Build Coastguard Worker help="directory to save .png proofs to disk.") 48*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('-v','--verbosity', 49*c8dee2aaSAndroid Build Coastguard Worker type=int, default=1, help="level of verbosity (0=none to 5=debug)") 50*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('-d', '--duration', 51*c8dee2aaSAndroid Build Coastguard Worker type=int, help="number of milliseconds to run each benchmark") 52*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('-l', '--sample-ms', 53*c8dee2aaSAndroid Build Coastguard Worker type=int, help="duration of a sample (minimum)") 54*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--gpu', 55*c8dee2aaSAndroid Build Coastguard Worker action='store_true', 56*c8dee2aaSAndroid Build Coastguard Worker help="perform timing on the gpu clock instead of cpu (gpu work only)") 57*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--fps', 58*c8dee2aaSAndroid Build Coastguard Worker action='store_true', help="use fps instead of ms") 59*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--pr', 60*c8dee2aaSAndroid Build Coastguard Worker help="comma- or space-separated list of GPU path renderers, including: " 61*c8dee2aaSAndroid Build Coastguard Worker "[[~]all [~]default [~]dashline [~]msaa [~]aaconvex " 62*c8dee2aaSAndroid Build Coastguard Worker "[~]aalinearizing [~]small [~]tess]") 63*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--cc', 64*c8dee2aaSAndroid Build Coastguard Worker action='store_true', help="allow coverage counting shortcuts to render paths") 65*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--nocache', 66*c8dee2aaSAndroid Build Coastguard Worker action='store_true', help="disable caching of path mask textures") 67*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--allPathsVolatile', 68*c8dee2aaSAndroid Build Coastguard Worker action='store_true', 69*c8dee2aaSAndroid Build Coastguard Worker help="Causes all GPU paths to be processed as if 'setIsVolatile' had been called.") 70*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('-c', '--config', 71*c8dee2aaSAndroid Build Coastguard Worker default='gl', help="comma- or space-separated list of GPU configs") 72*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('-a', '--resultsfile', 73*c8dee2aaSAndroid Build Coastguard Worker help="optional file to append results into") 74*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--ddl', 75*c8dee2aaSAndroid Build Coastguard Worker action='store_true', help="record the skp into DDLs before rendering") 76*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--lock-clocks', 77*c8dee2aaSAndroid Build Coastguard Worker action='store_true', help="Put device in benchmarking mode (locked clocks, no other processes)") 78*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--clock-speed', 79*c8dee2aaSAndroid Build Coastguard Worker type=float, default=66.0, help="A number between 0 and 100 indicating how fast to lock the CPU and GPU clock." 80*c8dee2aaSAndroid Build Coastguard Worker "Valid speeds are chosen from their respective available frequencies list.") 81*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--ddlNumRecordingThreads', 82*c8dee2aaSAndroid Build Coastguard Worker type=int, default=0, 83*c8dee2aaSAndroid Build Coastguard Worker help="number of DDL recording threads (0=num_cores)") 84*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--ddlTilingWidthHeight', 85*c8dee2aaSAndroid Build Coastguard Worker type=int, default=0, help="number of tiles along one edge when in DDL mode") 86*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--dontReduceOpsTaskSplitting', 87*c8dee2aaSAndroid Build Coastguard Worker action='store_true', help="don't reorder GPU tasks to reduce render target swaps") 88*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--gpuThreads', 89*c8dee2aaSAndroid Build Coastguard Worker type=int, default=-1, 90*c8dee2aaSAndroid Build Coastguard Worker help="Create this many extra threads to assist with GPU work, including" 91*c8dee2aaSAndroid Build Coastguard Worker " software path rendering. Defaults to two.") 92*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--internalSamples', 93*c8dee2aaSAndroid Build Coastguard Worker type=int, default=-1, 94*c8dee2aaSAndroid Build Coastguard Worker help="Number of samples for internal draws that use MSAA.") 95*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('srcs', 96*c8dee2aaSAndroid Build Coastguard Worker nargs='+', 97*c8dee2aaSAndroid Build Coastguard Worker help=".skp files or directories to expand for .skp files, and/or .svg files") 98*c8dee2aaSAndroid Build Coastguard Worker__argparse.add_argument('--gpuResourceCacheLimit', 99*c8dee2aaSAndroid Build Coastguard Worker type=int, default=-1, 100*c8dee2aaSAndroid Build Coastguard Worker help="Maximum number of bytes to use for budgeted GPU resources.") 101*c8dee2aaSAndroid Build Coastguard Worker 102*c8dee2aaSAndroid Build Coastguard WorkerFLAGS = __argparse.parse_args() 103*c8dee2aaSAndroid Build Coastguard Workerif FLAGS.adb: 104*c8dee2aaSAndroid Build Coastguard Worker import _adb_path as _path 105*c8dee2aaSAndroid Build Coastguard Worker _path.init(FLAGS.device_serial, FLAGS.adb_binary) 106*c8dee2aaSAndroid Build Coastguard Workerelse: 107*c8dee2aaSAndroid Build Coastguard Worker import _os_path as _path 108*c8dee2aaSAndroid Build Coastguard Worker 109*c8dee2aaSAndroid Build Coastguard Workerdef dump_commandline_if_verbose(commandline): 110*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.verbosity >= 5: 111*c8dee2aaSAndroid Build Coastguard Worker quoted = ['\'%s\'' % re.sub(r'([\\\'])', r'\\\1', x) for x in commandline] 112*c8dee2aaSAndroid Build Coastguard Worker print(' '.join(quoted), file=sys.stderr) 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Workerclass StddevException(Exception): 116*c8dee2aaSAndroid Build Coastguard Worker pass 117*c8dee2aaSAndroid Build Coastguard Worker 118*c8dee2aaSAndroid Build Coastguard Workerclass Message: 119*c8dee2aaSAndroid Build Coastguard Worker READLINE = 0, 120*c8dee2aaSAndroid Build Coastguard Worker POLL_HARDWARE = 1, 121*c8dee2aaSAndroid Build Coastguard Worker EXIT = 2 122*c8dee2aaSAndroid Build Coastguard Worker def __init__(self, message, value=None): 123*c8dee2aaSAndroid Build Coastguard Worker self.message = message 124*c8dee2aaSAndroid Build Coastguard Worker self.value = value 125*c8dee2aaSAndroid Build Coastguard Worker 126*c8dee2aaSAndroid Build Coastguard Workerclass SubprocessMonitor(Thread): 127*c8dee2aaSAndroid Build Coastguard Worker def __init__(self, queue, proc): 128*c8dee2aaSAndroid Build Coastguard Worker self._queue = queue 129*c8dee2aaSAndroid Build Coastguard Worker self._proc = proc 130*c8dee2aaSAndroid Build Coastguard Worker Thread.__init__(self) 131*c8dee2aaSAndroid Build Coastguard Worker 132*c8dee2aaSAndroid Build Coastguard Worker def run(self): 133*c8dee2aaSAndroid Build Coastguard Worker """Runs on the background thread.""" 134*c8dee2aaSAndroid Build Coastguard Worker for line in iter(self._proc.stdout.readline, b''): 135*c8dee2aaSAndroid Build Coastguard Worker self._queue.put(Message(Message.READLINE, line.decode('utf-8').rstrip())) 136*c8dee2aaSAndroid Build Coastguard Worker self._queue.put(Message(Message.EXIT)) 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Workerclass SKPBench: 139*c8dee2aaSAndroid Build Coastguard Worker ARGV = [FLAGS.skpbench, '--verbosity', str(FLAGS.verbosity)] 140*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.duration: 141*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--duration', str(FLAGS.duration)]) 142*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.sample_ms: 143*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--sampleMs', str(FLAGS.sample_ms)]) 144*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.gpu: 145*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--gpuClock', 'true']) 146*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.fps: 147*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--fps', 'true']) 148*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.pr: 149*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--pr'] + re.split(r'[ ,]', FLAGS.pr)) 150*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.cc: 151*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--cc', 'true']) 152*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.nocache: 153*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--cachePathMasks', 'false']) 154*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.allPathsVolatile: 155*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--allPathsVolatile', 'true']) 156*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.gpuThreads != -1: 157*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--gpuThreads', str(FLAGS.gpuThreads)]) 158*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.internalSamples != -1: 159*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--internalSamples', str(FLAGS.internalSamples)]) 160*c8dee2aaSAndroid Build Coastguard Worker 161*c8dee2aaSAndroid Build Coastguard Worker # DDL parameters 162*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.ddl: 163*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--ddl', 'true']) 164*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.ddlNumRecordingThreads: 165*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--ddlNumRecordingThreads', 166*c8dee2aaSAndroid Build Coastguard Worker str(FLAGS.ddlNumRecordingThreads)]) 167*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.ddlTilingWidthHeight: 168*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--ddlTilingWidthHeight', str(FLAGS.ddlTilingWidthHeight)]) 169*c8dee2aaSAndroid Build Coastguard Worker 170*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.dontReduceOpsTaskSplitting: 171*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--dontReduceOpsTaskSplitting']) 172*c8dee2aaSAndroid Build Coastguard Worker 173*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.gpuResourceCacheLimit: 174*c8dee2aaSAndroid Build Coastguard Worker ARGV.extend(['--gpuResourceCacheLimit', str(FLAGS.gpuResourceCacheLimit)]) 175*c8dee2aaSAndroid Build Coastguard Worker 176*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.adb: 177*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.device_serial is None: 178*c8dee2aaSAndroid Build Coastguard Worker ARGV[:0] = [FLAGS.adb_binary, 'shell'] 179*c8dee2aaSAndroid Build Coastguard Worker else: 180*c8dee2aaSAndroid Build Coastguard Worker ARGV[:0] = [FLAGS.adb_binary, '-s', FLAGS.device_serial, 'shell'] 181*c8dee2aaSAndroid Build Coastguard Worker 182*c8dee2aaSAndroid Build Coastguard Worker @classmethod 183*c8dee2aaSAndroid Build Coastguard Worker def get_header(cls, outfile=sys.stdout): 184*c8dee2aaSAndroid Build Coastguard Worker commandline = cls.ARGV + ['--duration', '0'] 185*c8dee2aaSAndroid Build Coastguard Worker dump_commandline_if_verbose(commandline) 186*c8dee2aaSAndroid Build Coastguard Worker out = subprocess.check_output(commandline, stderr=subprocess.STDOUT, encoding='utf-8') 187*c8dee2aaSAndroid Build Coastguard Worker return out.rstrip() 188*c8dee2aaSAndroid Build Coastguard Worker 189*c8dee2aaSAndroid Build Coastguard Worker @classmethod 190*c8dee2aaSAndroid Build Coastguard Worker def run_warmup(cls, warmup_time, config): 191*c8dee2aaSAndroid Build Coastguard Worker if not warmup_time: 192*c8dee2aaSAndroid Build Coastguard Worker return 193*c8dee2aaSAndroid Build Coastguard Worker print('running %i second warmup...' % warmup_time, file=sys.stderr) 194*c8dee2aaSAndroid Build Coastguard Worker commandline = cls.ARGV + ['--duration', str(warmup_time * 1000), 195*c8dee2aaSAndroid Build Coastguard Worker '--config', config, 196*c8dee2aaSAndroid Build Coastguard Worker '--src', 'warmup'] 197*c8dee2aaSAndroid Build Coastguard Worker dump_commandline_if_verbose(commandline) 198*c8dee2aaSAndroid Build Coastguard Worker output = subprocess.check_output(commandline, stderr=subprocess.STDOUT, encoding='utf-8') 199*c8dee2aaSAndroid Build Coastguard Worker 200*c8dee2aaSAndroid Build Coastguard Worker # validate the warmup run output. 201*c8dee2aaSAndroid Build Coastguard Worker for line in output.split('\n'): 202*c8dee2aaSAndroid Build Coastguard Worker match = BenchResult.match(line.rstrip()) 203*c8dee2aaSAndroid Build Coastguard Worker if match and match.bench == 'warmup': 204*c8dee2aaSAndroid Build Coastguard Worker return 205*c8dee2aaSAndroid Build Coastguard Worker raise Exception('Invalid warmup output:\n%s' % output) 206*c8dee2aaSAndroid Build Coastguard Worker 207*c8dee2aaSAndroid Build Coastguard Worker def __init__(self, src, config, max_stddev, best_result=None): 208*c8dee2aaSAndroid Build Coastguard Worker self.src = src 209*c8dee2aaSAndroid Build Coastguard Worker self.config = config 210*c8dee2aaSAndroid Build Coastguard Worker self.max_stddev = max_stddev 211*c8dee2aaSAndroid Build Coastguard Worker self.best_result = best_result 212*c8dee2aaSAndroid Build Coastguard Worker self._queue = Queue() 213*c8dee2aaSAndroid Build Coastguard Worker self._proc = None 214*c8dee2aaSAndroid Build Coastguard Worker self._monitor = None 215*c8dee2aaSAndroid Build Coastguard Worker self._hw_poll_timer = None 216*c8dee2aaSAndroid Build Coastguard Worker 217*c8dee2aaSAndroid Build Coastguard Worker def __enter__(self): 218*c8dee2aaSAndroid Build Coastguard Worker return self 219*c8dee2aaSAndroid Build Coastguard Worker 220*c8dee2aaSAndroid Build Coastguard Worker def __exit__(self, exception_type, exception_value, traceback): 221*c8dee2aaSAndroid Build Coastguard Worker if self._proc: 222*c8dee2aaSAndroid Build Coastguard Worker self.terminate() 223*c8dee2aaSAndroid Build Coastguard Worker if self._hw_poll_timer: 224*c8dee2aaSAndroid Build Coastguard Worker self._hw_poll_timer.cancel() 225*c8dee2aaSAndroid Build Coastguard Worker 226*c8dee2aaSAndroid Build Coastguard Worker def execute(self, hardware): 227*c8dee2aaSAndroid Build Coastguard Worker hardware.sanity_check() 228*c8dee2aaSAndroid Build Coastguard Worker self._schedule_hardware_poll() 229*c8dee2aaSAndroid Build Coastguard Worker 230*c8dee2aaSAndroid Build Coastguard Worker commandline = self.ARGV + ['--config', self.config, 231*c8dee2aaSAndroid Build Coastguard Worker '--src', self.src, 232*c8dee2aaSAndroid Build Coastguard Worker '--suppressHeader', 'true'] 233*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.write_path: 234*c8dee2aaSAndroid Build Coastguard Worker pngfile = _path.join(FLAGS.write_path, self.config, 235*c8dee2aaSAndroid Build Coastguard Worker _path.basename(self.src) + '.png') 236*c8dee2aaSAndroid Build Coastguard Worker commandline.extend(['--png', pngfile]) 237*c8dee2aaSAndroid Build Coastguard Worker dump_commandline_if_verbose(commandline) 238*c8dee2aaSAndroid Build Coastguard Worker self._proc = subprocess.Popen(commandline, stdout=subprocess.PIPE, 239*c8dee2aaSAndroid Build Coastguard Worker stderr=subprocess.STDOUT) 240*c8dee2aaSAndroid Build Coastguard Worker self._monitor = SubprocessMonitor(self._queue, self._proc) 241*c8dee2aaSAndroid Build Coastguard Worker self._monitor.start() 242*c8dee2aaSAndroid Build Coastguard Worker 243*c8dee2aaSAndroid Build Coastguard Worker while True: 244*c8dee2aaSAndroid Build Coastguard Worker message = self._queue.get() 245*c8dee2aaSAndroid Build Coastguard Worker if message.message == Message.READLINE: 246*c8dee2aaSAndroid Build Coastguard Worker result = BenchResult.match(message.value) 247*c8dee2aaSAndroid Build Coastguard Worker if result: 248*c8dee2aaSAndroid Build Coastguard Worker hardware.sanity_check() 249*c8dee2aaSAndroid Build Coastguard Worker self._process_result(result) 250*c8dee2aaSAndroid Build Coastguard Worker elif hardware.filter_line(message.value): 251*c8dee2aaSAndroid Build Coastguard Worker print(message.value, file=sys.stderr) 252*c8dee2aaSAndroid Build Coastguard Worker continue 253*c8dee2aaSAndroid Build Coastguard Worker if message.message == Message.POLL_HARDWARE: 254*c8dee2aaSAndroid Build Coastguard Worker hardware.sanity_check() 255*c8dee2aaSAndroid Build Coastguard Worker self._schedule_hardware_poll() 256*c8dee2aaSAndroid Build Coastguard Worker continue 257*c8dee2aaSAndroid Build Coastguard Worker if message.message == Message.EXIT: 258*c8dee2aaSAndroid Build Coastguard Worker self._monitor.join() 259*c8dee2aaSAndroid Build Coastguard Worker self._proc.wait() 260*c8dee2aaSAndroid Build Coastguard Worker if self._proc.returncode != 0: 261*c8dee2aaSAndroid Build Coastguard Worker raise Exception("skpbench exited with nonzero exit code %i" % 262*c8dee2aaSAndroid Build Coastguard Worker self._proc.returncode) 263*c8dee2aaSAndroid Build Coastguard Worker self._proc = None 264*c8dee2aaSAndroid Build Coastguard Worker break 265*c8dee2aaSAndroid Build Coastguard Worker 266*c8dee2aaSAndroid Build Coastguard Worker def _schedule_hardware_poll(self): 267*c8dee2aaSAndroid Build Coastguard Worker if self._hw_poll_timer: 268*c8dee2aaSAndroid Build Coastguard Worker self._hw_poll_timer.cancel() 269*c8dee2aaSAndroid Build Coastguard Worker self._hw_poll_timer = \ 270*c8dee2aaSAndroid Build Coastguard Worker Timer(1, lambda: self._queue.put(Message(Message.POLL_HARDWARE))) 271*c8dee2aaSAndroid Build Coastguard Worker self._hw_poll_timer.start() 272*c8dee2aaSAndroid Build Coastguard Worker 273*c8dee2aaSAndroid Build Coastguard Worker def _process_result(self, result): 274*c8dee2aaSAndroid Build Coastguard Worker if not self.best_result or result.stddev <= self.best_result.stddev: 275*c8dee2aaSAndroid Build Coastguard Worker self.best_result = result 276*c8dee2aaSAndroid Build Coastguard Worker elif FLAGS.verbosity >= 2: 277*c8dee2aaSAndroid Build Coastguard Worker print("reusing previous result for %s/%s with lower stddev " 278*c8dee2aaSAndroid Build Coastguard Worker "(%s%% instead of %s%%)." % 279*c8dee2aaSAndroid Build Coastguard Worker (result.config, result.bench, self.best_result.stddev, 280*c8dee2aaSAndroid Build Coastguard Worker result.stddev), file=sys.stderr) 281*c8dee2aaSAndroid Build Coastguard Worker if self.max_stddev and self.best_result.stddev > self.max_stddev: 282*c8dee2aaSAndroid Build Coastguard Worker raise StddevException() 283*c8dee2aaSAndroid Build Coastguard Worker 284*c8dee2aaSAndroid Build Coastguard Worker def terminate(self): 285*c8dee2aaSAndroid Build Coastguard Worker if self._proc: 286*c8dee2aaSAndroid Build Coastguard Worker self._proc.terminate() 287*c8dee2aaSAndroid Build Coastguard Worker self._monitor.join() 288*c8dee2aaSAndroid Build Coastguard Worker self._proc.wait() 289*c8dee2aaSAndroid Build Coastguard Worker self._proc = None 290*c8dee2aaSAndroid Build Coastguard Worker 291*c8dee2aaSAndroid Build Coastguard Workerdef emit_result(line, resultsfile=None): 292*c8dee2aaSAndroid Build Coastguard Worker print(line) 293*c8dee2aaSAndroid Build Coastguard Worker sys.stdout.flush() 294*c8dee2aaSAndroid Build Coastguard Worker if resultsfile: 295*c8dee2aaSAndroid Build Coastguard Worker print(line, file=resultsfile) 296*c8dee2aaSAndroid Build Coastguard Worker resultsfile.flush() 297*c8dee2aaSAndroid Build Coastguard Worker 298*c8dee2aaSAndroid Build Coastguard Workerdef run_benchmarks(configs, srcs, hardware, resultsfile=None): 299*c8dee2aaSAndroid Build Coastguard Worker hasheader = False 300*c8dee2aaSAndroid Build Coastguard Worker benches = collections.deque([(src, config, FLAGS.max_stddev) 301*c8dee2aaSAndroid Build Coastguard Worker for src in srcs 302*c8dee2aaSAndroid Build Coastguard Worker for config in configs]) 303*c8dee2aaSAndroid Build Coastguard Worker while benches: 304*c8dee2aaSAndroid Build Coastguard Worker try: 305*c8dee2aaSAndroid Build Coastguard Worker with hardware: 306*c8dee2aaSAndroid Build Coastguard Worker SKPBench.run_warmup(hardware.warmup_time, configs[0]) 307*c8dee2aaSAndroid Build Coastguard Worker if not hasheader: 308*c8dee2aaSAndroid Build Coastguard Worker emit_result(SKPBench.get_header(), resultsfile) 309*c8dee2aaSAndroid Build Coastguard Worker hasheader = True 310*c8dee2aaSAndroid Build Coastguard Worker while benches: 311*c8dee2aaSAndroid Build Coastguard Worker benchargs = benches.popleft() 312*c8dee2aaSAndroid Build Coastguard Worker with SKPBench(*benchargs) as skpbench: 313*c8dee2aaSAndroid Build Coastguard Worker try: 314*c8dee2aaSAndroid Build Coastguard Worker skpbench.execute(hardware) 315*c8dee2aaSAndroid Build Coastguard Worker if skpbench.best_result: 316*c8dee2aaSAndroid Build Coastguard Worker emit_result(skpbench.best_result.format(FLAGS.suffix), 317*c8dee2aaSAndroid Build Coastguard Worker resultsfile) 318*c8dee2aaSAndroid Build Coastguard Worker else: 319*c8dee2aaSAndroid Build Coastguard Worker print("WARNING: no result for %s with config %s" % 320*c8dee2aaSAndroid Build Coastguard Worker (skpbench.src, skpbench.config), file=sys.stderr) 321*c8dee2aaSAndroid Build Coastguard Worker 322*c8dee2aaSAndroid Build Coastguard Worker except StddevException: 323*c8dee2aaSAndroid Build Coastguard Worker retry_max_stddev = skpbench.max_stddev * math.sqrt(2) 324*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.verbosity >= 1: 325*c8dee2aaSAndroid Build Coastguard Worker print("stddev is too high for %s/%s (%s%%, max=%.2f%%), " 326*c8dee2aaSAndroid Build Coastguard Worker "re-queuing with max=%.2f%%." % 327*c8dee2aaSAndroid Build Coastguard Worker (skpbench.best_result.config, skpbench.best_result.bench, 328*c8dee2aaSAndroid Build Coastguard Worker skpbench.best_result.stddev, skpbench.max_stddev, 329*c8dee2aaSAndroid Build Coastguard Worker retry_max_stddev), 330*c8dee2aaSAndroid Build Coastguard Worker file=sys.stderr) 331*c8dee2aaSAndroid Build Coastguard Worker benches.append((skpbench.src, skpbench.config, retry_max_stddev, 332*c8dee2aaSAndroid Build Coastguard Worker skpbench.best_result)) 333*c8dee2aaSAndroid Build Coastguard Worker 334*c8dee2aaSAndroid Build Coastguard Worker except HardwareException as exception: 335*c8dee2aaSAndroid Build Coastguard Worker skpbench.terminate() 336*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.verbosity >= 4: 337*c8dee2aaSAndroid Build Coastguard Worker hardware.print_debug_diagnostics() 338*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.verbosity >= 1: 339*c8dee2aaSAndroid Build Coastguard Worker print("%s; rebooting and taking a %i second nap..." % 340*c8dee2aaSAndroid Build Coastguard Worker (exception.message, exception.sleeptime), file=sys.stderr) 341*c8dee2aaSAndroid Build Coastguard Worker benches.appendleft(benchargs) # retry the same bench next time. 342*c8dee2aaSAndroid Build Coastguard Worker raise # wake hw up from benchmarking mode before the nap. 343*c8dee2aaSAndroid Build Coastguard Worker 344*c8dee2aaSAndroid Build Coastguard Worker except HardwareException as exception: 345*c8dee2aaSAndroid Build Coastguard Worker time.sleep(exception.sleeptime) 346*c8dee2aaSAndroid Build Coastguard Worker 347*c8dee2aaSAndroid Build Coastguard Workerdef main(): 348*c8dee2aaSAndroid Build Coastguard Worker # Delimiter is ',' or ' ', skip if nested inside parens (e.g. gpu(a=b,c=d)). 349*c8dee2aaSAndroid Build Coastguard Worker DELIMITER = r'[, ](?!(?:[^(]*\([^)]*\))*[^()]*\))' 350*c8dee2aaSAndroid Build Coastguard Worker configs = re.split(DELIMITER, FLAGS.config) 351*c8dee2aaSAndroid Build Coastguard Worker srcs = _path.find_skps(FLAGS.srcs) 352*c8dee2aaSAndroid Build Coastguard Worker assert srcs 353*c8dee2aaSAndroid Build Coastguard Worker 354*c8dee2aaSAndroid Build Coastguard Worker 355*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.adb: 356*c8dee2aaSAndroid Build Coastguard Worker adb = Adb(FLAGS.device_serial, FLAGS.adb_binary, 357*c8dee2aaSAndroid Build Coastguard Worker echo=(FLAGS.verbosity >= 5)) 358*c8dee2aaSAndroid Build Coastguard Worker from _hardware_android import HardwareAndroid 359*c8dee2aaSAndroid Build Coastguard Worker 360*c8dee2aaSAndroid Build Coastguard Worker model = adb.check('getprop ro.product.model').strip() 361*c8dee2aaSAndroid Build Coastguard Worker if model == 'Pixel C': 362*c8dee2aaSAndroid Build Coastguard Worker from _hardware_pixel_c import HardwarePixelC 363*c8dee2aaSAndroid Build Coastguard Worker hardware = HardwarePixelC(adb) 364*c8dee2aaSAndroid Build Coastguard Worker elif model == 'Pixel' or model == "Pixel XL": 365*c8dee2aaSAndroid Build Coastguard Worker from _hardware_pixel import HardwarePixel 366*c8dee2aaSAndroid Build Coastguard Worker hardware = HardwarePixel(adb) 367*c8dee2aaSAndroid Build Coastguard Worker elif model == 'Pixel 2': 368*c8dee2aaSAndroid Build Coastguard Worker from _hardware_pixel2 import HardwarePixel2 369*c8dee2aaSAndroid Build Coastguard Worker hardware = HardwarePixel2(adb) 370*c8dee2aaSAndroid Build Coastguard Worker elif model == 'Nexus 6P': 371*c8dee2aaSAndroid Build Coastguard Worker from _hardware_nexus_6p import HardwareNexus6P 372*c8dee2aaSAndroid Build Coastguard Worker hardware = HardwareNexus6P(adb) 373*c8dee2aaSAndroid Build Coastguard Worker else: 374*c8dee2aaSAndroid Build Coastguard Worker print("WARNING: %s: don't know how to monitor this hardware; results " 375*c8dee2aaSAndroid Build Coastguard Worker "may be unreliable." % model, file=sys.stderr) 376*c8dee2aaSAndroid Build Coastguard Worker hardware = HardwareAndroid(adb) 377*c8dee2aaSAndroid Build Coastguard Worker 378*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.lock_clocks: 379*c8dee2aaSAndroid Build Coastguard Worker hardware.__enter__() 380*c8dee2aaSAndroid Build Coastguard Worker print("Entered benchmarking mode, not running benchmarks. Reboot to restore."); 381*c8dee2aaSAndroid Build Coastguard Worker return; 382*c8dee2aaSAndroid Build Coastguard Worker 383*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.clock_speed: 384*c8dee2aaSAndroid Build Coastguard Worker hardware.setDesiredClock(FLAGS.clock_speed) 385*c8dee2aaSAndroid Build Coastguard Worker else: 386*c8dee2aaSAndroid Build Coastguard Worker hardware = Hardware() 387*c8dee2aaSAndroid Build Coastguard Worker 388*c8dee2aaSAndroid Build Coastguard Worker if FLAGS.resultsfile: 389*c8dee2aaSAndroid Build Coastguard Worker with open(FLAGS.resultsfile, mode='a+') as resultsfile: 390*c8dee2aaSAndroid Build Coastguard Worker run_benchmarks(configs, srcs, hardware, resultsfile=resultsfile) 391*c8dee2aaSAndroid Build Coastguard Worker else: 392*c8dee2aaSAndroid Build Coastguard Worker run_benchmarks(configs, srcs, hardware) 393*c8dee2aaSAndroid Build Coastguard Worker 394*c8dee2aaSAndroid Build Coastguard Worker 395*c8dee2aaSAndroid Build Coastguard Workerif __name__ == '__main__': 396*c8dee2aaSAndroid Build Coastguard Worker main() 397