blob: 157d4497a14e6d2238bd3ad4bcaf839d271ffb15 [file] [log] [blame]
Corentin Wallez59382b72020-04-17 20:43:07 +00001#!/usr/bin/env python3
Austin Engca0eac32019-08-28 23:18:10 +00002#
3# Copyright 2019 The Dawn Authors
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# Based on Angle's perf_test_runner.py
18
19import glob
20import subprocess
21import sys
22import os
23import re
24
Kai Ninomiya01aeca22020-07-15 19:51:17 +000025base_path = os.path.abspath(
26 os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
Austin Engca0eac32019-08-28 23:18:10 +000027
28# Look for a [Rr]elease build.
29perftests_paths = glob.glob('out/*elease*')
30metric = 'wall_time'
31max_experiments = 10
32
33binary_name = 'dawn_perf_tests'
34if sys.platform == 'win32':
35 binary_name += '.exe'
36
37scores = []
38
Kai Ninomiya01aeca22020-07-15 19:51:17 +000039
Austin Engca0eac32019-08-28 23:18:10 +000040def mean(data):
41 """Return the sample arithmetic mean of data."""
42 n = len(data)
43 if n < 1:
44 raise ValueError('mean requires at least one data point')
45 return float(sum(data)) / float(n) # in Python 2 use sum(data)/float(n)
46
47
48def sum_of_square_deviations(data, c):
49 """Return sum of square deviations of sequence data."""
50 ss = sum((float(x) - c)**2 for x in data)
51 return ss
52
53
54def coefficient_of_variation(data):
55 """Calculates the population coefficient of variation."""
56 n = len(data)
57 if n < 2:
58 raise ValueError('variance requires at least two data points')
59 c = mean(data)
60 ss = sum_of_square_deviations(data, c)
61 pvar = ss / n # the population variance
62 stddev = (pvar**0.5) # population standard deviation
63 return stddev / c
64
65
66def truncated_list(data, n):
67 """Compute a truncated list, n is truncation size"""
68 if len(data) < n * 2:
69 raise ValueError('list not large enough to truncate')
70 return sorted(data)[n:-n]
71
72
73def truncated_mean(data, n):
74 """Compute a truncated mean, n is truncation size"""
75 return mean(truncated_list(data, n))
76
77
78def truncated_cov(data, n):
79 """Compute a truncated coefficient of variation, n is truncation size"""
80 return coefficient_of_variation(truncated_list(data, n))
81
82
83# Find most recent binary
84newest_binary = None
85newest_mtime = None
86
87for path in perftests_paths:
88 binary_path = os.path.join(base_path, path, binary_name)
89 if os.path.exists(binary_path):
90 binary_mtime = os.path.getmtime(binary_path)
91 if (newest_binary is None) or (binary_mtime > newest_mtime):
92 newest_binary = binary_path
93 newest_mtime = binary_mtime
94
95perftests_path = newest_binary
96
97if perftests_path == None or not os.path.exists(perftests_path):
98 print('Cannot find Release %s!' % binary_name)
99 sys.exit(1)
100
101if len(sys.argv) >= 2:
102 test_name = sys.argv[1]
103
104print('Using test executable: ' + perftests_path)
105print('Test name: ' + test_name)
106
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000107
Austin Engca0eac32019-08-28 23:18:10 +0000108def get_results(metric, extra_args=[]):
109 process = subprocess.Popen(
110 [perftests_path, '--gtest_filter=' + test_name] + extra_args,
111 stdout=subprocess.PIPE,
112 stderr=subprocess.PIPE)
113 output, err = process.communicate()
114
115 m = re.search(r'Running (\d+) tests', output)
116 if m and int(m.group(1)) > 1:
117 print("Found more than one test result in output:")
118 print(output)
119 sys.exit(3)
120
Bryan Bernhart4b1be082020-03-26 17:46:25 +0000121 pattern = metric + r'.*= ([0-9.]+)'
Austin Engca0eac32019-08-28 23:18:10 +0000122 m = re.findall(pattern, output)
Bryan Bernhart4b1be082020-03-26 17:46:25 +0000123 if not m:
Austin Engca0eac32019-08-28 23:18:10 +0000124 print("Did not find the metric '%s' in the test output:" % metric)
125 print(output)
126 sys.exit(1)
127
128 return [float(value) for value in m]
129
130
131# Calibrate the number of steps
132steps = get_results("steps", ["--calibration"])[0]
133print("running with %d steps." % steps)
134
135# Loop 'max_experiments' times, running the tests.
136for experiment in range(max_experiments):
137 experiment_scores = get_results(metric, ["--override-steps", str(steps)])
138
139 for score in experiment_scores:
140 sys.stdout.write("%s: %.2f" % (metric, score))
141 scores.append(score)
142
143 if (len(scores) > 1):
144 sys.stdout.write(", mean: %.2f" % mean(scores))
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000145 sys.stdout.write(", variation: %.2f%%" %
146 (coefficient_of_variation(scores) * 100.0))
Austin Engca0eac32019-08-28 23:18:10 +0000147
148 if (len(scores) > 7):
149 truncation_n = len(scores) >> 3
Kai Ninomiya01aeca22020-07-15 19:51:17 +0000150 sys.stdout.write(", truncated mean: %.2f" %
151 truncated_mean(scores, truncation_n))
152 sys.stdout.write(", variation: %.2f%%" %
153 (truncated_cov(scores, truncation_n) * 100.0))
Austin Engca0eac32019-08-28 23:18:10 +0000154
155 print("")