1*8975f5c5SAndroid Build Coastguard Worker#! /usr/bin/env vpython3 2*8975f5c5SAndroid Build Coastguard Worker# 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2021 The ANGLE Project Authors. All rights reserved. 4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 6*8975f5c5SAndroid Build Coastguard Worker# 7*8975f5c5SAndroid Build Coastguard Worker# run_perf_test.py: 8*8975f5c5SAndroid Build Coastguard Worker# Runs ANGLE perf tests using some statistical averaging. 9*8975f5c5SAndroid Build Coastguard Worker 10*8975f5c5SAndroid Build Coastguard Workerimport argparse 11*8975f5c5SAndroid Build Coastguard Workerimport contextlib 12*8975f5c5SAndroid Build Coastguard Workerimport glob 13*8975f5c5SAndroid Build Coastguard Workerimport importlib 14*8975f5c5SAndroid Build Coastguard Workerimport io 15*8975f5c5SAndroid Build Coastguard Workerimport json 16*8975f5c5SAndroid Build Coastguard Workerimport logging 17*8975f5c5SAndroid Build Coastguard Workerimport tempfile 18*8975f5c5SAndroid Build Coastguard Workerimport time 19*8975f5c5SAndroid Build Coastguard Workerimport os 20*8975f5c5SAndroid Build Coastguard Workerimport pathlib 21*8975f5c5SAndroid Build Coastguard Workerimport re 22*8975f5c5SAndroid Build Coastguard Workerimport subprocess 23*8975f5c5SAndroid Build Coastguard Workerimport shutil 24*8975f5c5SAndroid Build Coastguard Workerimport sys 25*8975f5c5SAndroid Build Coastguard Worker 26*8975f5c5SAndroid Build Coastguard WorkerSCRIPT_DIR = str(pathlib.Path(__file__).resolve().parent) 27*8975f5c5SAndroid Build Coastguard WorkerPY_UTILS = str(pathlib.Path(SCRIPT_DIR) / 'py_utils') 28*8975f5c5SAndroid Build Coastguard Workerif PY_UTILS not in sys.path: 29*8975f5c5SAndroid Build Coastguard Worker os.stat(PY_UTILS) and sys.path.insert(0, PY_UTILS) 30*8975f5c5SAndroid Build Coastguard Workerimport android_helper 31*8975f5c5SAndroid Build Coastguard Workerimport angle_metrics 32*8975f5c5SAndroid Build Coastguard Workerimport angle_path_util 33*8975f5c5SAndroid Build Coastguard Workerimport angle_test_util 34*8975f5c5SAndroid Build Coastguard Worker 35*8975f5c5SAndroid Build Coastguard Workerangle_path_util.AddDepsDirToPath('testing/scripts') 36*8975f5c5SAndroid Build Coastguard Workerimport common 37*8975f5c5SAndroid Build Coastguard Worker 38*8975f5c5SAndroid Build Coastguard Workerangle_path_util.AddDepsDirToPath('third_party/catapult/tracing') 39*8975f5c5SAndroid Build Coastguard Workerfrom tracing.value import histogram 40*8975f5c5SAndroid Build Coastguard Workerfrom tracing.value import histogram_set 41*8975f5c5SAndroid Build Coastguard Workerfrom tracing.value import merge_histograms 42*8975f5c5SAndroid Build Coastguard Worker 43*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_TEST_SUITE = 'angle_perftests' 44*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_LOG = 'info' 45*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_SAMPLES = 10 46*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_TRIALS = 4 47*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_MAX_ERRORS = 3 48*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_TRIAL_TIME = 3 49*8975f5c5SAndroid Build Coastguard Worker 50*8975f5c5SAndroid Build Coastguard Worker# Test expectations 51*8975f5c5SAndroid Build Coastguard WorkerFAIL = 'FAIL' 52*8975f5c5SAndroid Build Coastguard WorkerPASS = 'PASS' 53*8975f5c5SAndroid Build Coastguard WorkerSKIP = 'SKIP' 54*8975f5c5SAndroid Build Coastguard Worker 55*8975f5c5SAndroid Build Coastguard WorkerEXIT_FAILURE = 1 56*8975f5c5SAndroid Build Coastguard WorkerEXIT_SUCCESS = 0 57*8975f5c5SAndroid Build Coastguard Worker 58*8975f5c5SAndroid Build Coastguard Worker 59*8975f5c5SAndroid Build Coastguard Worker@contextlib.contextmanager 60*8975f5c5SAndroid Build Coastguard Workerdef temporary_dir(prefix=''): 61*8975f5c5SAndroid Build Coastguard Worker path = tempfile.mkdtemp(prefix=prefix) 62*8975f5c5SAndroid Build Coastguard Worker try: 63*8975f5c5SAndroid Build Coastguard Worker yield path 64*8975f5c5SAndroid Build Coastguard Worker finally: 65*8975f5c5SAndroid Build Coastguard Worker shutil.rmtree(path) 66*8975f5c5SAndroid Build Coastguard Worker 67*8975f5c5SAndroid Build Coastguard Worker 68*8975f5c5SAndroid Build Coastguard Workerdef _shard_tests(tests, shard_count, shard_index): 69*8975f5c5SAndroid Build Coastguard Worker return [tests[index] for index in range(shard_index, len(tests), shard_count)] 70*8975f5c5SAndroid Build Coastguard Worker 71*8975f5c5SAndroid Build Coastguard Worker 72*8975f5c5SAndroid Build Coastguard Workerdef _get_results_from_output(output, result): 73*8975f5c5SAndroid Build Coastguard Worker m = re.search(r'Running (\d+) tests', output) 74*8975f5c5SAndroid Build Coastguard Worker if m and int(m.group(1)) > 1: 75*8975f5c5SAndroid Build Coastguard Worker raise Exception('Found more than one test result in output') 76*8975f5c5SAndroid Build Coastguard Worker 77*8975f5c5SAndroid Build Coastguard Worker # Results are reported in the format: 78*8975f5c5SAndroid Build Coastguard Worker # name_backend.result: story= value units. 79*8975f5c5SAndroid Build Coastguard Worker pattern = r'\.' + result + r':.*= ([0-9.]+)' 80*8975f5c5SAndroid Build Coastguard Worker logging.debug('Searching for %s in output' % pattern) 81*8975f5c5SAndroid Build Coastguard Worker m = re.findall(pattern, output) 82*8975f5c5SAndroid Build Coastguard Worker if not m: 83*8975f5c5SAndroid Build Coastguard Worker logging.warning('Did not find the result "%s" in the test output:\n%s' % (result, output)) 84*8975f5c5SAndroid Build Coastguard Worker return None 85*8975f5c5SAndroid Build Coastguard Worker 86*8975f5c5SAndroid Build Coastguard Worker return [float(value) for value in m] 87*8975f5c5SAndroid Build Coastguard Worker 88*8975f5c5SAndroid Build Coastguard Worker 89*8975f5c5SAndroid Build Coastguard Workerdef _truncated_list(data, n): 90*8975f5c5SAndroid Build Coastguard Worker """Compute a truncated list, n is truncation size""" 91*8975f5c5SAndroid Build Coastguard Worker if len(data) < n * 2: 92*8975f5c5SAndroid Build Coastguard Worker raise ValueError('list not large enough to truncate') 93*8975f5c5SAndroid Build Coastguard Worker return sorted(data)[n:-n] 94*8975f5c5SAndroid Build Coastguard Worker 95*8975f5c5SAndroid Build Coastguard Worker 96*8975f5c5SAndroid Build Coastguard Workerdef _mean(data): 97*8975f5c5SAndroid Build Coastguard Worker """Return the sample arithmetic mean of data.""" 98*8975f5c5SAndroid Build Coastguard Worker n = len(data) 99*8975f5c5SAndroid Build Coastguard Worker if n < 1: 100*8975f5c5SAndroid Build Coastguard Worker raise ValueError('mean requires at least one data point') 101*8975f5c5SAndroid Build Coastguard Worker return float(sum(data)) / float(n) # in Python 2 use sum(data)/float(n) 102*8975f5c5SAndroid Build Coastguard Worker 103*8975f5c5SAndroid Build Coastguard Worker 104*8975f5c5SAndroid Build Coastguard Workerdef _sum_of_square_deviations(data, c): 105*8975f5c5SAndroid Build Coastguard Worker """Return sum of square deviations of sequence data.""" 106*8975f5c5SAndroid Build Coastguard Worker ss = sum((float(x) - c)**2 for x in data) 107*8975f5c5SAndroid Build Coastguard Worker return ss 108*8975f5c5SAndroid Build Coastguard Worker 109*8975f5c5SAndroid Build Coastguard Worker 110*8975f5c5SAndroid Build Coastguard Workerdef _coefficient_of_variation(data): 111*8975f5c5SAndroid Build Coastguard Worker """Calculates the population coefficient of variation.""" 112*8975f5c5SAndroid Build Coastguard Worker n = len(data) 113*8975f5c5SAndroid Build Coastguard Worker if n < 2: 114*8975f5c5SAndroid Build Coastguard Worker raise ValueError('variance requires at least two data points') 115*8975f5c5SAndroid Build Coastguard Worker c = _mean(data) 116*8975f5c5SAndroid Build Coastguard Worker ss = _sum_of_square_deviations(data, c) 117*8975f5c5SAndroid Build Coastguard Worker pvar = ss / n # the population variance 118*8975f5c5SAndroid Build Coastguard Worker stddev = (pvar**0.5) # population standard deviation 119*8975f5c5SAndroid Build Coastguard Worker return stddev / c 120*8975f5c5SAndroid Build Coastguard Worker 121*8975f5c5SAndroid Build Coastguard Worker 122*8975f5c5SAndroid Build Coastguard Workerdef _save_extra_output_files(args, results, histograms, metrics): 123*8975f5c5SAndroid Build Coastguard Worker isolated_out_dir = os.path.dirname(args.isolated_script_test_output) 124*8975f5c5SAndroid Build Coastguard Worker if not os.path.isdir(isolated_out_dir): 125*8975f5c5SAndroid Build Coastguard Worker return 126*8975f5c5SAndroid Build Coastguard Worker benchmark_path = os.path.join(isolated_out_dir, args.test_suite) 127*8975f5c5SAndroid Build Coastguard Worker if not os.path.isdir(benchmark_path): 128*8975f5c5SAndroid Build Coastguard Worker os.makedirs(benchmark_path) 129*8975f5c5SAndroid Build Coastguard Worker test_output_path = os.path.join(benchmark_path, 'test_results.json') 130*8975f5c5SAndroid Build Coastguard Worker results.save_to_json_file(test_output_path) 131*8975f5c5SAndroid Build Coastguard Worker perf_output_path = os.path.join(benchmark_path, 'perf_results.json') 132*8975f5c5SAndroid Build Coastguard Worker logging.info('Saving perf histograms to %s.' % perf_output_path) 133*8975f5c5SAndroid Build Coastguard Worker with open(perf_output_path, 'w') as out_file: 134*8975f5c5SAndroid Build Coastguard Worker out_file.write(json.dumps(histograms.AsDicts(), indent=2)) 135*8975f5c5SAndroid Build Coastguard Worker 136*8975f5c5SAndroid Build Coastguard Worker angle_metrics_path = os.path.join(benchmark_path, 'angle_metrics.json') 137*8975f5c5SAndroid Build Coastguard Worker with open(angle_metrics_path, 'w') as f: 138*8975f5c5SAndroid Build Coastguard Worker f.write(json.dumps(metrics, indent=2)) 139*8975f5c5SAndroid Build Coastguard Worker 140*8975f5c5SAndroid Build Coastguard Worker # Calling here to catch errors earlier (fail shard instead of merge script) 141*8975f5c5SAndroid Build Coastguard Worker assert angle_metrics.ConvertToSkiaPerf([angle_metrics_path]) 142*8975f5c5SAndroid Build Coastguard Worker 143*8975f5c5SAndroid Build Coastguard Worker 144*8975f5c5SAndroid Build Coastguard Workerclass Results: 145*8975f5c5SAndroid Build Coastguard Worker 146*8975f5c5SAndroid Build Coastguard Worker def __init__(self, suffix): 147*8975f5c5SAndroid Build Coastguard Worker self._results = { 148*8975f5c5SAndroid Build Coastguard Worker 'tests': {}, 149*8975f5c5SAndroid Build Coastguard Worker 'interrupted': False, 150*8975f5c5SAndroid Build Coastguard Worker 'seconds_since_epoch': time.time(), 151*8975f5c5SAndroid Build Coastguard Worker 'path_delimiter': '.', 152*8975f5c5SAndroid Build Coastguard Worker 'version': 3, 153*8975f5c5SAndroid Build Coastguard Worker 'num_failures_by_type': { 154*8975f5c5SAndroid Build Coastguard Worker FAIL: 0, 155*8975f5c5SAndroid Build Coastguard Worker PASS: 0, 156*8975f5c5SAndroid Build Coastguard Worker SKIP: 0, 157*8975f5c5SAndroid Build Coastguard Worker }, 158*8975f5c5SAndroid Build Coastguard Worker } 159*8975f5c5SAndroid Build Coastguard Worker self._test_results = {} 160*8975f5c5SAndroid Build Coastguard Worker self._suffix = suffix 161*8975f5c5SAndroid Build Coastguard Worker 162*8975f5c5SAndroid Build Coastguard Worker def _testname(self, name): 163*8975f5c5SAndroid Build Coastguard Worker return name + self._suffix 164*8975f5c5SAndroid Build Coastguard Worker 165*8975f5c5SAndroid Build Coastguard Worker def has_failures(self): 166*8975f5c5SAndroid Build Coastguard Worker return self._results['num_failures_by_type'][FAIL] > 0 167*8975f5c5SAndroid Build Coastguard Worker 168*8975f5c5SAndroid Build Coastguard Worker def has_result(self, test): 169*8975f5c5SAndroid Build Coastguard Worker return self._testname(test) in self._test_results 170*8975f5c5SAndroid Build Coastguard Worker 171*8975f5c5SAndroid Build Coastguard Worker def result_skip(self, test): 172*8975f5c5SAndroid Build Coastguard Worker self._test_results[self._testname(test)] = {'expected': SKIP, 'actual': SKIP} 173*8975f5c5SAndroid Build Coastguard Worker self._results['num_failures_by_type'][SKIP] += 1 174*8975f5c5SAndroid Build Coastguard Worker 175*8975f5c5SAndroid Build Coastguard Worker def result_pass(self, test): 176*8975f5c5SAndroid Build Coastguard Worker self._test_results[self._testname(test)] = {'expected': PASS, 'actual': PASS} 177*8975f5c5SAndroid Build Coastguard Worker self._results['num_failures_by_type'][PASS] += 1 178*8975f5c5SAndroid Build Coastguard Worker 179*8975f5c5SAndroid Build Coastguard Worker def result_fail(self, test): 180*8975f5c5SAndroid Build Coastguard Worker self._test_results[self._testname(test)] = { 181*8975f5c5SAndroid Build Coastguard Worker 'expected': PASS, 182*8975f5c5SAndroid Build Coastguard Worker 'actual': FAIL, 183*8975f5c5SAndroid Build Coastguard Worker 'is_unexpected': True 184*8975f5c5SAndroid Build Coastguard Worker } 185*8975f5c5SAndroid Build Coastguard Worker self._results['num_failures_by_type'][FAIL] += 1 186*8975f5c5SAndroid Build Coastguard Worker 187*8975f5c5SAndroid Build Coastguard Worker def save_to_output_file(self, test_suite, fname): 188*8975f5c5SAndroid Build Coastguard Worker self._update_results(test_suite) 189*8975f5c5SAndroid Build Coastguard Worker with open(fname, 'w') as out_file: 190*8975f5c5SAndroid Build Coastguard Worker out_file.write(json.dumps(self._results, indent=2)) 191*8975f5c5SAndroid Build Coastguard Worker 192*8975f5c5SAndroid Build Coastguard Worker def save_to_json_file(self, fname): 193*8975f5c5SAndroid Build Coastguard Worker logging.info('Saving test results to %s.' % fname) 194*8975f5c5SAndroid Build Coastguard Worker with open(fname, 'w') as out_file: 195*8975f5c5SAndroid Build Coastguard Worker out_file.write(json.dumps(self._results, indent=2)) 196*8975f5c5SAndroid Build Coastguard Worker 197*8975f5c5SAndroid Build Coastguard Worker def _update_results(self, test_suite): 198*8975f5c5SAndroid Build Coastguard Worker if self._test_results: 199*8975f5c5SAndroid Build Coastguard Worker self._results['tests'][test_suite] = self._test_results 200*8975f5c5SAndroid Build Coastguard Worker self._test_results = {} 201*8975f5c5SAndroid Build Coastguard Worker 202*8975f5c5SAndroid Build Coastguard Worker 203*8975f5c5SAndroid Build Coastguard Workerdef _read_histogram(histogram_file_path): 204*8975f5c5SAndroid Build Coastguard Worker with open(histogram_file_path) as histogram_file: 205*8975f5c5SAndroid Build Coastguard Worker histogram = histogram_set.HistogramSet() 206*8975f5c5SAndroid Build Coastguard Worker histogram.ImportDicts(json.load(histogram_file)) 207*8975f5c5SAndroid Build Coastguard Worker return histogram 208*8975f5c5SAndroid Build Coastguard Worker 209*8975f5c5SAndroid Build Coastguard Worker 210*8975f5c5SAndroid Build Coastguard Workerdef _read_metrics(metrics_file_path): 211*8975f5c5SAndroid Build Coastguard Worker try: 212*8975f5c5SAndroid Build Coastguard Worker with open(metrics_file_path) as f: 213*8975f5c5SAndroid Build Coastguard Worker return [json.loads(l) for l in f] 214*8975f5c5SAndroid Build Coastguard Worker except FileNotFoundError: 215*8975f5c5SAndroid Build Coastguard Worker return [] 216*8975f5c5SAndroid Build Coastguard Worker 217*8975f5c5SAndroid Build Coastguard Worker 218*8975f5c5SAndroid Build Coastguard Workerdef _merge_into_one_histogram(test_histogram_set): 219*8975f5c5SAndroid Build Coastguard Worker with common.temporary_file() as merge_histogram_path: 220*8975f5c5SAndroid Build Coastguard Worker logging.info('Writing merged histograms to %s.' % merge_histogram_path) 221*8975f5c5SAndroid Build Coastguard Worker with open(merge_histogram_path, 'w') as merge_histogram_file: 222*8975f5c5SAndroid Build Coastguard Worker json.dump(test_histogram_set.AsDicts(), merge_histogram_file) 223*8975f5c5SAndroid Build Coastguard Worker merge_histogram_file.close() 224*8975f5c5SAndroid Build Coastguard Worker merged_dicts = merge_histograms.MergeHistograms(merge_histogram_path, groupby=['name']) 225*8975f5c5SAndroid Build Coastguard Worker merged_histogram = histogram_set.HistogramSet() 226*8975f5c5SAndroid Build Coastguard Worker merged_histogram.ImportDicts(merged_dicts) 227*8975f5c5SAndroid Build Coastguard Worker return merged_histogram 228*8975f5c5SAndroid Build Coastguard Worker 229*8975f5c5SAndroid Build Coastguard Worker 230*8975f5c5SAndroid Build Coastguard Workerdef _wall_times_stats(wall_times): 231*8975f5c5SAndroid Build Coastguard Worker if len(wall_times) > 7: 232*8975f5c5SAndroid Build Coastguard Worker truncation_n = len(wall_times) >> 3 233*8975f5c5SAndroid Build Coastguard Worker logging.debug('Truncation: Removing the %d highest and lowest times from wall_times.' % 234*8975f5c5SAndroid Build Coastguard Worker truncation_n) 235*8975f5c5SAndroid Build Coastguard Worker wall_times = _truncated_list(wall_times, truncation_n) 236*8975f5c5SAndroid Build Coastguard Worker 237*8975f5c5SAndroid Build Coastguard Worker if len(wall_times) > 1: 238*8975f5c5SAndroid Build Coastguard Worker return ('truncated mean wall_time = %.2f, cov = %.2f%%' % 239*8975f5c5SAndroid Build Coastguard Worker (_mean(wall_times), _coefficient_of_variation(wall_times) * 100.0)) 240*8975f5c5SAndroid Build Coastguard Worker 241*8975f5c5SAndroid Build Coastguard Worker return None 242*8975f5c5SAndroid Build Coastguard Worker 243*8975f5c5SAndroid Build Coastguard Worker 244*8975f5c5SAndroid Build Coastguard Workerdef _run_test_suite(args, cmd_args, env): 245*8975f5c5SAndroid Build Coastguard Worker return angle_test_util.RunTestSuite( 246*8975f5c5SAndroid Build Coastguard Worker args.test_suite, 247*8975f5c5SAndroid Build Coastguard Worker cmd_args, 248*8975f5c5SAndroid Build Coastguard Worker env, 249*8975f5c5SAndroid Build Coastguard Worker use_xvfb=args.xvfb, 250*8975f5c5SAndroid Build Coastguard Worker show_test_stdout=args.show_test_stdout) 251*8975f5c5SAndroid Build Coastguard Worker 252*8975f5c5SAndroid Build Coastguard Worker 253*8975f5c5SAndroid Build Coastguard Workerdef _run_perf(args, common_args, env, steps_per_trial=None): 254*8975f5c5SAndroid Build Coastguard Worker run_args = common_args + [ 255*8975f5c5SAndroid Build Coastguard Worker '--trials', 256*8975f5c5SAndroid Build Coastguard Worker str(args.trials_per_sample), 257*8975f5c5SAndroid Build Coastguard Worker ] 258*8975f5c5SAndroid Build Coastguard Worker 259*8975f5c5SAndroid Build Coastguard Worker if steps_per_trial: 260*8975f5c5SAndroid Build Coastguard Worker run_args += ['--steps-per-trial', str(steps_per_trial)] 261*8975f5c5SAndroid Build Coastguard Worker else: 262*8975f5c5SAndroid Build Coastguard Worker run_args += ['--trial-time', str(args.trial_time)] 263*8975f5c5SAndroid Build Coastguard Worker 264*8975f5c5SAndroid Build Coastguard Worker if not args.smoke_test_mode: 265*8975f5c5SAndroid Build Coastguard Worker run_args += ['--warmup'] # Render each frame once with glFinish 266*8975f5c5SAndroid Build Coastguard Worker 267*8975f5c5SAndroid Build Coastguard Worker if args.perf_counters: 268*8975f5c5SAndroid Build Coastguard Worker run_args += ['--perf-counters', args.perf_counters] 269*8975f5c5SAndroid Build Coastguard Worker 270*8975f5c5SAndroid Build Coastguard Worker with temporary_dir() as render_output_dir: 271*8975f5c5SAndroid Build Coastguard Worker histogram_file_path = os.path.join(render_output_dir, 'histogram') 272*8975f5c5SAndroid Build Coastguard Worker run_args += ['--isolated-script-test-perf-output=%s' % histogram_file_path] 273*8975f5c5SAndroid Build Coastguard Worker run_args += ['--render-test-output-dir=%s' % render_output_dir] 274*8975f5c5SAndroid Build Coastguard Worker 275*8975f5c5SAndroid Build Coastguard Worker exit_code, output, json_results = _run_test_suite(args, run_args, env) 276*8975f5c5SAndroid Build Coastguard Worker if exit_code != EXIT_SUCCESS: 277*8975f5c5SAndroid Build Coastguard Worker raise RuntimeError('%s failed. Output:\n%s' % (args.test_suite, output)) 278*8975f5c5SAndroid Build Coastguard Worker if SKIP in json_results['num_failures_by_type']: 279*8975f5c5SAndroid Build Coastguard Worker return SKIP, None, None 280*8975f5c5SAndroid Build Coastguard Worker 281*8975f5c5SAndroid Build Coastguard Worker # Extract debug files for https://issuetracker.google.com/296921272 282*8975f5c5SAndroid Build Coastguard Worker if args.isolated_script_test_output: 283*8975f5c5SAndroid Build Coastguard Worker isolated_out_dir = os.path.dirname(args.isolated_script_test_output) 284*8975f5c5SAndroid Build Coastguard Worker for path in glob.glob(os.path.join(render_output_dir, '*gzdbg*')): 285*8975f5c5SAndroid Build Coastguard Worker shutil.move(path, isolated_out_dir) 286*8975f5c5SAndroid Build Coastguard Worker 287*8975f5c5SAndroid Build Coastguard Worker sample_metrics = _read_metrics(os.path.join(render_output_dir, 'angle_metrics')) 288*8975f5c5SAndroid Build Coastguard Worker 289*8975f5c5SAndroid Build Coastguard Worker if sample_metrics: 290*8975f5c5SAndroid Build Coastguard Worker sample_histogram = _read_histogram(histogram_file_path) 291*8975f5c5SAndroid Build Coastguard Worker return PASS, sample_metrics, sample_histogram 292*8975f5c5SAndroid Build Coastguard Worker 293*8975f5c5SAndroid Build Coastguard Worker return FAIL, None, None 294*8975f5c5SAndroid Build Coastguard Worker 295*8975f5c5SAndroid Build Coastguard Worker 296*8975f5c5SAndroid Build Coastguard Workerclass _MaxErrorsException(Exception): 297*8975f5c5SAndroid Build Coastguard Worker pass 298*8975f5c5SAndroid Build Coastguard Worker 299*8975f5c5SAndroid Build Coastguard Worker 300*8975f5c5SAndroid Build Coastguard Workerdef _skipped_or_glmark2(test, test_status): 301*8975f5c5SAndroid Build Coastguard Worker if test_status == SKIP: 302*8975f5c5SAndroid Build Coastguard Worker logging.info('Test skipped by suite: %s' % test) 303*8975f5c5SAndroid Build Coastguard Worker return True 304*8975f5c5SAndroid Build Coastguard Worker 305*8975f5c5SAndroid Build Coastguard Worker # GLMark2Benchmark logs .fps/.score instead of our perf metrics. 306*8975f5c5SAndroid Build Coastguard Worker if test.startswith('GLMark2Benchmark.Run/'): 307*8975f5c5SAndroid Build Coastguard Worker logging.info('GLMark2Benchmark missing metrics (as expected, skipping): %s' % test) 308*8975f5c5SAndroid Build Coastguard Worker return True 309*8975f5c5SAndroid Build Coastguard Worker 310*8975f5c5SAndroid Build Coastguard Worker return False 311*8975f5c5SAndroid Build Coastguard Worker 312*8975f5c5SAndroid Build Coastguard Worker 313*8975f5c5SAndroid Build Coastguard Workerdef _sleep_until_temps_below(limit_temp): 314*8975f5c5SAndroid Build Coastguard Worker while True: 315*8975f5c5SAndroid Build Coastguard Worker max_temp = max(android_helper.GetTemps()) 316*8975f5c5SAndroid Build Coastguard Worker if max_temp < limit_temp: 317*8975f5c5SAndroid Build Coastguard Worker break 318*8975f5c5SAndroid Build Coastguard Worker logging.info('Waiting for device temps below %.1f, curently %.1f', limit_temp, max_temp) 319*8975f5c5SAndroid Build Coastguard Worker time.sleep(10) 320*8975f5c5SAndroid Build Coastguard Worker 321*8975f5c5SAndroid Build Coastguard Worker 322*8975f5c5SAndroid Build Coastguard Workerdef _maybe_throttle_or_log_temps(custom_throttling_temp): 323*8975f5c5SAndroid Build Coastguard Worker is_debug = logging.getLogger().isEnabledFor(logging.DEBUG) 324*8975f5c5SAndroid Build Coastguard Worker 325*8975f5c5SAndroid Build Coastguard Worker if angle_test_util.IsAndroid(): 326*8975f5c5SAndroid Build Coastguard Worker if custom_throttling_temp: 327*8975f5c5SAndroid Build Coastguard Worker _sleep_until_temps_below(custom_throttling_temp) 328*8975f5c5SAndroid Build Coastguard Worker elif is_debug: 329*8975f5c5SAndroid Build Coastguard Worker android_helper.GetTemps() # calls log.debug 330*8975f5c5SAndroid Build Coastguard Worker elif sys.platform == 'linux' and is_debug: 331*8975f5c5SAndroid Build Coastguard Worker out = subprocess.check_output('cat /sys/class/hwmon/hwmon*/temp*_input', shell=True) 332*8975f5c5SAndroid Build Coastguard Worker logging.debug('hwmon temps: %s', 333*8975f5c5SAndroid Build Coastguard Worker ','.join([str(int(n) // 1000) for n in out.decode().split('\n') if n])) 334*8975f5c5SAndroid Build Coastguard Worker 335*8975f5c5SAndroid Build Coastguard Worker 336*8975f5c5SAndroid Build Coastguard Workerdef _run_tests(tests, args, extra_flags, env): 337*8975f5c5SAndroid Build Coastguard Worker if args.split_shard_samples and args.shard_index is not None: 338*8975f5c5SAndroid Build Coastguard Worker test_suffix = Results('_shard%d' % args.shard_index) 339*8975f5c5SAndroid Build Coastguard Worker else: 340*8975f5c5SAndroid Build Coastguard Worker test_suffix = '' 341*8975f5c5SAndroid Build Coastguard Worker 342*8975f5c5SAndroid Build Coastguard Worker results = Results(test_suffix) 343*8975f5c5SAndroid Build Coastguard Worker 344*8975f5c5SAndroid Build Coastguard Worker histograms = histogram_set.HistogramSet() 345*8975f5c5SAndroid Build Coastguard Worker metrics = [] 346*8975f5c5SAndroid Build Coastguard Worker total_errors = 0 347*8975f5c5SAndroid Build Coastguard Worker prepared_traces = set() 348*8975f5c5SAndroid Build Coastguard Worker 349*8975f5c5SAndroid Build Coastguard Worker for test_index in range(len(tests)): 350*8975f5c5SAndroid Build Coastguard Worker if total_errors >= args.max_errors: 351*8975f5c5SAndroid Build Coastguard Worker raise _MaxErrorsException() 352*8975f5c5SAndroid Build Coastguard Worker 353*8975f5c5SAndroid Build Coastguard Worker test = tests[test_index] 354*8975f5c5SAndroid Build Coastguard Worker 355*8975f5c5SAndroid Build Coastguard Worker if angle_test_util.IsAndroid(): 356*8975f5c5SAndroid Build Coastguard Worker trace = android_helper.GetTraceFromTestName(test) 357*8975f5c5SAndroid Build Coastguard Worker if trace and trace not in prepared_traces: 358*8975f5c5SAndroid Build Coastguard Worker android_helper.PrepareRestrictedTraces([trace]) 359*8975f5c5SAndroid Build Coastguard Worker prepared_traces.add(trace) 360*8975f5c5SAndroid Build Coastguard Worker 361*8975f5c5SAndroid Build Coastguard Worker common_args = [ 362*8975f5c5SAndroid Build Coastguard Worker '--gtest_filter=%s' % test, 363*8975f5c5SAndroid Build Coastguard Worker '--verbose', 364*8975f5c5SAndroid Build Coastguard Worker ] + extra_flags 365*8975f5c5SAndroid Build Coastguard Worker 366*8975f5c5SAndroid Build Coastguard Worker if args.steps_per_trial: 367*8975f5c5SAndroid Build Coastguard Worker steps_per_trial = args.steps_per_trial 368*8975f5c5SAndroid Build Coastguard Worker trial_limit = 'steps_per_trial=%d' % steps_per_trial 369*8975f5c5SAndroid Build Coastguard Worker else: 370*8975f5c5SAndroid Build Coastguard Worker steps_per_trial = None 371*8975f5c5SAndroid Build Coastguard Worker trial_limit = 'trial_time=%d' % args.trial_time 372*8975f5c5SAndroid Build Coastguard Worker 373*8975f5c5SAndroid Build Coastguard Worker logging.info('Test %d/%d: %s (samples=%d trials_per_sample=%d %s)' % 374*8975f5c5SAndroid Build Coastguard Worker (test_index + 1, len(tests), test, args.samples_per_test, 375*8975f5c5SAndroid Build Coastguard Worker args.trials_per_sample, trial_limit)) 376*8975f5c5SAndroid Build Coastguard Worker 377*8975f5c5SAndroid Build Coastguard Worker wall_times = [] 378*8975f5c5SAndroid Build Coastguard Worker test_histogram_set = histogram_set.HistogramSet() 379*8975f5c5SAndroid Build Coastguard Worker for sample in range(args.samples_per_test): 380*8975f5c5SAndroid Build Coastguard Worker try: 381*8975f5c5SAndroid Build Coastguard Worker _maybe_throttle_or_log_temps(args.custom_throttling_temp) 382*8975f5c5SAndroid Build Coastguard Worker test_status, sample_metrics, sample_histogram = _run_perf( 383*8975f5c5SAndroid Build Coastguard Worker args, common_args, env, steps_per_trial) 384*8975f5c5SAndroid Build Coastguard Worker except RuntimeError as e: 385*8975f5c5SAndroid Build Coastguard Worker logging.error(e) 386*8975f5c5SAndroid Build Coastguard Worker results.result_fail(test) 387*8975f5c5SAndroid Build Coastguard Worker total_errors += 1 388*8975f5c5SAndroid Build Coastguard Worker break 389*8975f5c5SAndroid Build Coastguard Worker 390*8975f5c5SAndroid Build Coastguard Worker if _skipped_or_glmark2(test, test_status): 391*8975f5c5SAndroid Build Coastguard Worker results.result_skip(test) 392*8975f5c5SAndroid Build Coastguard Worker break 393*8975f5c5SAndroid Build Coastguard Worker 394*8975f5c5SAndroid Build Coastguard Worker if not sample_metrics: 395*8975f5c5SAndroid Build Coastguard Worker logging.error('Test %s failed to produce a sample output' % test) 396*8975f5c5SAndroid Build Coastguard Worker results.result_fail(test) 397*8975f5c5SAndroid Build Coastguard Worker break 398*8975f5c5SAndroid Build Coastguard Worker 399*8975f5c5SAndroid Build Coastguard Worker sample_wall_times = [ 400*8975f5c5SAndroid Build Coastguard Worker float(m['value']) for m in sample_metrics if m['metric'] == '.wall_time' 401*8975f5c5SAndroid Build Coastguard Worker ] 402*8975f5c5SAndroid Build Coastguard Worker 403*8975f5c5SAndroid Build Coastguard Worker logging.info('Test %d/%d Sample %d/%d wall_times: %s' % 404*8975f5c5SAndroid Build Coastguard Worker (test_index + 1, len(tests), sample + 1, args.samples_per_test, 405*8975f5c5SAndroid Build Coastguard Worker str(sample_wall_times))) 406*8975f5c5SAndroid Build Coastguard Worker 407*8975f5c5SAndroid Build Coastguard Worker if len(sample_wall_times) != args.trials_per_sample: 408*8975f5c5SAndroid Build Coastguard Worker logging.error('Test %s failed to record some wall_times (expected %d, got %d)' % 409*8975f5c5SAndroid Build Coastguard Worker (test, args.trials_per_sample, len(sample_wall_times))) 410*8975f5c5SAndroid Build Coastguard Worker results.result_fail(test) 411*8975f5c5SAndroid Build Coastguard Worker break 412*8975f5c5SAndroid Build Coastguard Worker 413*8975f5c5SAndroid Build Coastguard Worker wall_times += sample_wall_times 414*8975f5c5SAndroid Build Coastguard Worker test_histogram_set.Merge(sample_histogram) 415*8975f5c5SAndroid Build Coastguard Worker metrics.append(sample_metrics) 416*8975f5c5SAndroid Build Coastguard Worker 417*8975f5c5SAndroid Build Coastguard Worker if not results.has_result(test): 418*8975f5c5SAndroid Build Coastguard Worker assert len(wall_times) == (args.samples_per_test * args.trials_per_sample) 419*8975f5c5SAndroid Build Coastguard Worker stats = _wall_times_stats(wall_times) 420*8975f5c5SAndroid Build Coastguard Worker if stats: 421*8975f5c5SAndroid Build Coastguard Worker logging.info('Test %d/%d: %s: %s' % (test_index + 1, len(tests), test, stats)) 422*8975f5c5SAndroid Build Coastguard Worker histograms.Merge(_merge_into_one_histogram(test_histogram_set)) 423*8975f5c5SAndroid Build Coastguard Worker results.result_pass(test) 424*8975f5c5SAndroid Build Coastguard Worker 425*8975f5c5SAndroid Build Coastguard Worker return results, histograms, metrics 426*8975f5c5SAndroid Build Coastguard Worker 427*8975f5c5SAndroid Build Coastguard Worker 428*8975f5c5SAndroid Build Coastguard Workerdef _find_test_suite_directory(test_suite): 429*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(angle_test_util.ExecutablePathInCurrentDir(test_suite)): 430*8975f5c5SAndroid Build Coastguard Worker return '.' 431*8975f5c5SAndroid Build Coastguard Worker 432*8975f5c5SAndroid Build Coastguard Worker if angle_test_util.IsWindows(): 433*8975f5c5SAndroid Build Coastguard Worker test_suite += '.exe' 434*8975f5c5SAndroid Build Coastguard Worker 435*8975f5c5SAndroid Build Coastguard Worker # Find most recent binary in search paths. 436*8975f5c5SAndroid Build Coastguard Worker newest_binary = None 437*8975f5c5SAndroid Build Coastguard Worker newest_mtime = None 438*8975f5c5SAndroid Build Coastguard Worker 439*8975f5c5SAndroid Build Coastguard Worker for path in glob.glob('out/*'): 440*8975f5c5SAndroid Build Coastguard Worker binary_path = str(pathlib.Path(SCRIPT_DIR).parent.parent / path / test_suite) 441*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(binary_path): 442*8975f5c5SAndroid Build Coastguard Worker binary_mtime = os.path.getmtime(binary_path) 443*8975f5c5SAndroid Build Coastguard Worker if (newest_binary is None) or (binary_mtime > newest_mtime): 444*8975f5c5SAndroid Build Coastguard Worker newest_binary = binary_path 445*8975f5c5SAndroid Build Coastguard Worker newest_mtime = binary_mtime 446*8975f5c5SAndroid Build Coastguard Worker 447*8975f5c5SAndroid Build Coastguard Worker if newest_binary: 448*8975f5c5SAndroid Build Coastguard Worker logging.info('Found %s in %s' % (test_suite, os.path.dirname(newest_binary))) 449*8975f5c5SAndroid Build Coastguard Worker return os.path.dirname(newest_binary) 450*8975f5c5SAndroid Build Coastguard Worker return None 451*8975f5c5SAndroid Build Coastguard Worker 452*8975f5c5SAndroid Build Coastguard Worker 453*8975f5c5SAndroid Build Coastguard Workerdef _split_shard_samples(tests, samples_per_test, shard_count, shard_index): 454*8975f5c5SAndroid Build Coastguard Worker test_samples = [(test, sample) for test in tests for sample in range(samples_per_test)] 455*8975f5c5SAndroid Build Coastguard Worker shard_test_samples = _shard_tests(test_samples, shard_count, shard_index) 456*8975f5c5SAndroid Build Coastguard Worker return [test for (test, sample) in shard_test_samples] 457*8975f5c5SAndroid Build Coastguard Worker 458*8975f5c5SAndroid Build Coastguard Worker 459*8975f5c5SAndroid Build Coastguard Workerdef _should_lock_gpu_clocks(): 460*8975f5c5SAndroid Build Coastguard Worker if not angle_test_util.IsWindows(): 461*8975f5c5SAndroid Build Coastguard Worker return False 462*8975f5c5SAndroid Build Coastguard Worker 463*8975f5c5SAndroid Build Coastguard Worker try: 464*8975f5c5SAndroid Build Coastguard Worker gpu_info = subprocess.check_output( 465*8975f5c5SAndroid Build Coastguard Worker ['nvidia-smi', '--query-gpu=gpu_name', '--format=csv,noheader']).decode() 466*8975f5c5SAndroid Build Coastguard Worker except FileNotFoundError: 467*8975f5c5SAndroid Build Coastguard Worker # expected in some cases, e.g. non-nvidia bots 468*8975f5c5SAndroid Build Coastguard Worker return False 469*8975f5c5SAndroid Build Coastguard Worker 470*8975f5c5SAndroid Build Coastguard Worker logging.info('nvidia-smi --query-gpu=gpu_name output: %s' % gpu_info) 471*8975f5c5SAndroid Build Coastguard Worker 472*8975f5c5SAndroid Build Coastguard Worker return gpu_info.strip() == 'GeForce GTX 1660' 473*8975f5c5SAndroid Build Coastguard Worker 474*8975f5c5SAndroid Build Coastguard Worker 475*8975f5c5SAndroid Build Coastguard Workerdef _log_nvidia_gpu_temperature(): 476*8975f5c5SAndroid Build Coastguard Worker t = subprocess.check_output( 477*8975f5c5SAndroid Build Coastguard Worker ['nvidia-smi', '--query-gpu=temperature.gpu', '--format=csv,noheader']).decode().strip() 478*8975f5c5SAndroid Build Coastguard Worker logging.info('Current GPU temperature: %s ' % t) 479*8975f5c5SAndroid Build Coastguard Worker 480*8975f5c5SAndroid Build Coastguard Worker 481*8975f5c5SAndroid Build Coastguard Worker@contextlib.contextmanager 482*8975f5c5SAndroid Build Coastguard Workerdef _maybe_lock_gpu_clocks(): 483*8975f5c5SAndroid Build Coastguard Worker if not _should_lock_gpu_clocks(): 484*8975f5c5SAndroid Build Coastguard Worker yield 485*8975f5c5SAndroid Build Coastguard Worker return 486*8975f5c5SAndroid Build Coastguard Worker 487*8975f5c5SAndroid Build Coastguard Worker # Lock to 1410Mhz (`nvidia-smi --query-supported-clocks=gr --format=csv`) 488*8975f5c5SAndroid Build Coastguard Worker lgc_out = subprocess.check_output(['nvidia-smi', '--lock-gpu-clocks=1410,1410']).decode() 489*8975f5c5SAndroid Build Coastguard Worker logging.info('Lock GPU clocks output: %s' % lgc_out) 490*8975f5c5SAndroid Build Coastguard Worker _log_nvidia_gpu_temperature() 491*8975f5c5SAndroid Build Coastguard Worker try: 492*8975f5c5SAndroid Build Coastguard Worker yield 493*8975f5c5SAndroid Build Coastguard Worker finally: 494*8975f5c5SAndroid Build Coastguard Worker rgc_out = subprocess.check_output(['nvidia-smi', '--reset-gpu-clocks']).decode() 495*8975f5c5SAndroid Build Coastguard Worker logging.info('Reset GPU clocks output: %s' % rgc_out) 496*8975f5c5SAndroid Build Coastguard Worker _log_nvidia_gpu_temperature() 497*8975f5c5SAndroid Build Coastguard Worker 498*8975f5c5SAndroid Build Coastguard Worker 499*8975f5c5SAndroid Build Coastguard Workerdef main(): 500*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 501*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--isolated-script-test-output', type=str) 502*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--isolated-script-test-perf-output', type=str) 503*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 504*8975f5c5SAndroid Build Coastguard Worker '-f', '--filter', '--isolated-script-test-filter', type=str, help='Test filter.') 505*8975f5c5SAndroid Build Coastguard Worker suite_group = parser.add_mutually_exclusive_group() 506*8975f5c5SAndroid Build Coastguard Worker suite_group.add_argument( 507*8975f5c5SAndroid Build Coastguard Worker '--test-suite', '--suite', help='Test suite to run.', default=DEFAULT_TEST_SUITE) 508*8975f5c5SAndroid Build Coastguard Worker suite_group.add_argument( 509*8975f5c5SAndroid Build Coastguard Worker '-T', 510*8975f5c5SAndroid Build Coastguard Worker '--trace-tests', 511*8975f5c5SAndroid Build Coastguard Worker help='Run with the angle_trace_tests test suite.', 512*8975f5c5SAndroid Build Coastguard Worker action='store_true') 513*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--xvfb', help='Use xvfb.', action='store_true') 514*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 515*8975f5c5SAndroid Build Coastguard Worker '--shard-count', 516*8975f5c5SAndroid Build Coastguard Worker help='Number of shards for test splitting. Default is 1.', 517*8975f5c5SAndroid Build Coastguard Worker type=int, 518*8975f5c5SAndroid Build Coastguard Worker default=1) 519*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 520*8975f5c5SAndroid Build Coastguard Worker '--shard-index', 521*8975f5c5SAndroid Build Coastguard Worker help='Index of the current shard for test splitting. Default is 0.', 522*8975f5c5SAndroid Build Coastguard Worker type=int, 523*8975f5c5SAndroid Build Coastguard Worker default=0) 524*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 525*8975f5c5SAndroid Build Coastguard Worker '-l', '--log', help='Log output level. Default is %s.' % DEFAULT_LOG, default=DEFAULT_LOG) 526*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 527*8975f5c5SAndroid Build Coastguard Worker '-s', 528*8975f5c5SAndroid Build Coastguard Worker '--samples-per-test', 529*8975f5c5SAndroid Build Coastguard Worker help='Number of samples to run per test. Default is %d.' % DEFAULT_SAMPLES, 530*8975f5c5SAndroid Build Coastguard Worker type=int, 531*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_SAMPLES) 532*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 533*8975f5c5SAndroid Build Coastguard Worker '-t', 534*8975f5c5SAndroid Build Coastguard Worker '--trials-per-sample', 535*8975f5c5SAndroid Build Coastguard Worker help='Number of trials to run per sample. Default is %d.' % DEFAULT_TRIALS, 536*8975f5c5SAndroid Build Coastguard Worker type=int, 537*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_TRIALS) 538*8975f5c5SAndroid Build Coastguard Worker trial_group = parser.add_mutually_exclusive_group() 539*8975f5c5SAndroid Build Coastguard Worker trial_group.add_argument( 540*8975f5c5SAndroid Build Coastguard Worker '--steps-per-trial', help='Fixed number of steps to run per trial.', type=int) 541*8975f5c5SAndroid Build Coastguard Worker trial_group.add_argument( 542*8975f5c5SAndroid Build Coastguard Worker '--trial-time', 543*8975f5c5SAndroid Build Coastguard Worker help='Number of seconds to run per trial. Default is %d.' % DEFAULT_TRIAL_TIME, 544*8975f5c5SAndroid Build Coastguard Worker type=int, 545*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_TRIAL_TIME) 546*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 547*8975f5c5SAndroid Build Coastguard Worker '--max-errors', 548*8975f5c5SAndroid Build Coastguard Worker help='After this many errors, abort the run. Default is %d.' % DEFAULT_MAX_ERRORS, 549*8975f5c5SAndroid Build Coastguard Worker type=int, 550*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_MAX_ERRORS) 551*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 552*8975f5c5SAndroid Build Coastguard Worker '--smoke-test-mode', help='Do a quick run to validate correctness.', action='store_true') 553*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 554*8975f5c5SAndroid Build Coastguard Worker '--show-test-stdout', help='Prints all test stdout during execution.', action='store_true') 555*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 556*8975f5c5SAndroid Build Coastguard Worker '--perf-counters', help='Colon-separated list of extra perf counter metrics.') 557*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 558*8975f5c5SAndroid Build Coastguard Worker '-a', 559*8975f5c5SAndroid Build Coastguard Worker '--auto-dir', 560*8975f5c5SAndroid Build Coastguard Worker help='Run with the most recent test suite found in the build directories.', 561*8975f5c5SAndroid Build Coastguard Worker action='store_true') 562*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 563*8975f5c5SAndroid Build Coastguard Worker '--split-shard-samples', 564*8975f5c5SAndroid Build Coastguard Worker help='Attempt to mitigate variance between machines by splitting samples between shards.', 565*8975f5c5SAndroid Build Coastguard Worker action='store_true') 566*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 567*8975f5c5SAndroid Build Coastguard Worker '--custom-throttling-temp', 568*8975f5c5SAndroid Build Coastguard Worker help='Android: custom thermal throttling with limit set to this temperature (off by default)', 569*8975f5c5SAndroid Build Coastguard Worker type=float) 570*8975f5c5SAndroid Build Coastguard Worker 571*8975f5c5SAndroid Build Coastguard Worker args, extra_flags = parser.parse_known_args() 572*8975f5c5SAndroid Build Coastguard Worker 573*8975f5c5SAndroid Build Coastguard Worker if args.trace_tests: 574*8975f5c5SAndroid Build Coastguard Worker args.test_suite = angle_test_util.ANGLE_TRACE_TEST_SUITE 575*8975f5c5SAndroid Build Coastguard Worker 576*8975f5c5SAndroid Build Coastguard Worker angle_test_util.SetupLogging(args.log.upper()) 577*8975f5c5SAndroid Build Coastguard Worker 578*8975f5c5SAndroid Build Coastguard Worker start_time = time.time() 579*8975f5c5SAndroid Build Coastguard Worker 580*8975f5c5SAndroid Build Coastguard Worker # Use fast execution for smoke test mode. 581*8975f5c5SAndroid Build Coastguard Worker if args.smoke_test_mode: 582*8975f5c5SAndroid Build Coastguard Worker args.steps_per_trial = 1 583*8975f5c5SAndroid Build Coastguard Worker args.trials_per_sample = 1 584*8975f5c5SAndroid Build Coastguard Worker args.samples_per_test = 1 585*8975f5c5SAndroid Build Coastguard Worker 586*8975f5c5SAndroid Build Coastguard Worker env = os.environ.copy() 587*8975f5c5SAndroid Build Coastguard Worker 588*8975f5c5SAndroid Build Coastguard Worker if angle_test_util.HasGtestShardsAndIndex(env): 589*8975f5c5SAndroid Build Coastguard Worker args.shard_count, args.shard_index = angle_test_util.PopGtestShardsAndIndex(env) 590*8975f5c5SAndroid Build Coastguard Worker 591*8975f5c5SAndroid Build Coastguard Worker if args.auto_dir: 592*8975f5c5SAndroid Build Coastguard Worker test_suite_dir = _find_test_suite_directory(args.test_suite) 593*8975f5c5SAndroid Build Coastguard Worker if not test_suite_dir: 594*8975f5c5SAndroid Build Coastguard Worker logging.fatal('Could not find test suite: %s' % args.test_suite) 595*8975f5c5SAndroid Build Coastguard Worker return EXIT_FAILURE 596*8975f5c5SAndroid Build Coastguard Worker else: 597*8975f5c5SAndroid Build Coastguard Worker os.chdir(test_suite_dir) 598*8975f5c5SAndroid Build Coastguard Worker 599*8975f5c5SAndroid Build Coastguard Worker angle_test_util.Initialize(args.test_suite) 600*8975f5c5SAndroid Build Coastguard Worker 601*8975f5c5SAndroid Build Coastguard Worker # Get test list 602*8975f5c5SAndroid Build Coastguard Worker exit_code, output, _ = _run_test_suite(args, ['--list-tests', '--verbose'] + extra_flags, env) 603*8975f5c5SAndroid Build Coastguard Worker if exit_code != EXIT_SUCCESS: 604*8975f5c5SAndroid Build Coastguard Worker logging.fatal('Could not find test list from test output:\n%s' % output) 605*8975f5c5SAndroid Build Coastguard Worker sys.exit(EXIT_FAILURE) 606*8975f5c5SAndroid Build Coastguard Worker tests = angle_test_util.GetTestsFromOutput(output) 607*8975f5c5SAndroid Build Coastguard Worker 608*8975f5c5SAndroid Build Coastguard Worker if args.filter: 609*8975f5c5SAndroid Build Coastguard Worker tests = angle_test_util.FilterTests(tests, args.filter) 610*8975f5c5SAndroid Build Coastguard Worker 611*8975f5c5SAndroid Build Coastguard Worker # Get tests for this shard (if using sharding args) 612*8975f5c5SAndroid Build Coastguard Worker if args.split_shard_samples and args.shard_count >= args.samples_per_test: 613*8975f5c5SAndroid Build Coastguard Worker tests = _split_shard_samples(tests, args.samples_per_test, args.shard_count, 614*8975f5c5SAndroid Build Coastguard Worker args.shard_index) 615*8975f5c5SAndroid Build Coastguard Worker assert (len(set(tests)) == len(tests)) 616*8975f5c5SAndroid Build Coastguard Worker args.samples_per_test = 1 617*8975f5c5SAndroid Build Coastguard Worker else: 618*8975f5c5SAndroid Build Coastguard Worker tests = _shard_tests(tests, args.shard_count, args.shard_index) 619*8975f5c5SAndroid Build Coastguard Worker 620*8975f5c5SAndroid Build Coastguard Worker if not tests: 621*8975f5c5SAndroid Build Coastguard Worker logging.error('No tests to run.') 622*8975f5c5SAndroid Build Coastguard Worker return EXIT_FAILURE 623*8975f5c5SAndroid Build Coastguard Worker 624*8975f5c5SAndroid Build Coastguard Worker logging.info('Running %d test%s' % (len(tests), 's' if len(tests) > 1 else ' ')) 625*8975f5c5SAndroid Build Coastguard Worker 626*8975f5c5SAndroid Build Coastguard Worker try: 627*8975f5c5SAndroid Build Coastguard Worker with _maybe_lock_gpu_clocks(): 628*8975f5c5SAndroid Build Coastguard Worker results, histograms, metrics = _run_tests(tests, args, extra_flags, env) 629*8975f5c5SAndroid Build Coastguard Worker except _MaxErrorsException: 630*8975f5c5SAndroid Build Coastguard Worker logging.error('Error count exceeded max errors (%d). Aborting.' % args.max_errors) 631*8975f5c5SAndroid Build Coastguard Worker return EXIT_FAILURE 632*8975f5c5SAndroid Build Coastguard Worker 633*8975f5c5SAndroid Build Coastguard Worker for test in tests: 634*8975f5c5SAndroid Build Coastguard Worker assert results.has_result(test) 635*8975f5c5SAndroid Build Coastguard Worker 636*8975f5c5SAndroid Build Coastguard Worker if args.isolated_script_test_output: 637*8975f5c5SAndroid Build Coastguard Worker results.save_to_output_file(args.test_suite, args.isolated_script_test_output) 638*8975f5c5SAndroid Build Coastguard Worker 639*8975f5c5SAndroid Build Coastguard Worker # Uses special output files to match the merge script. 640*8975f5c5SAndroid Build Coastguard Worker _save_extra_output_files(args, results, histograms, metrics) 641*8975f5c5SAndroid Build Coastguard Worker 642*8975f5c5SAndroid Build Coastguard Worker if args.isolated_script_test_perf_output: 643*8975f5c5SAndroid Build Coastguard Worker with open(args.isolated_script_test_perf_output, 'w') as out_file: 644*8975f5c5SAndroid Build Coastguard Worker out_file.write(json.dumps(histograms.AsDicts(), indent=2)) 645*8975f5c5SAndroid Build Coastguard Worker 646*8975f5c5SAndroid Build Coastguard Worker end_time = time.time() 647*8975f5c5SAndroid Build Coastguard Worker logging.info('Elapsed time: %.2lf seconds.' % (end_time - start_time)) 648*8975f5c5SAndroid Build Coastguard Worker 649*8975f5c5SAndroid Build Coastguard Worker if results.has_failures(): 650*8975f5c5SAndroid Build Coastguard Worker return EXIT_FAILURE 651*8975f5c5SAndroid Build Coastguard Worker return EXIT_SUCCESS 652*8975f5c5SAndroid Build Coastguard Worker 653*8975f5c5SAndroid Build Coastguard Worker 654*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 655*8975f5c5SAndroid Build Coastguard Worker sys.exit(main()) 656