blob: f9d924b30845ddca89f6dac5d20469ca342f6f36 [file] [log] [blame]
Jamie Madilld6dfe672015-11-20 12:18:12 -05001#!/usr/bin/python
2#
3# Copyright 2015 The ANGLE Project Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6#
7# perf_test_runner.py:
8# Helper script for running and analyzing perftest results. Runs the
9# tests in an infinite batch, printing out the mean and standard
10# deviation of the population continuously.
11#
12
13import subprocess
14import sys
15import os
Olli Etuahod39f8932015-12-17 17:10:02 +020016import re
17
18base_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
Jamie Madilld6dfe672015-11-20 12:18:12 -050019
20# You might have to re-order these to find the specific version you want.
Olli Etuahod39f8932015-12-17 17:10:02 +020021perftests_paths = [
Jamie Madill1fbc59f2016-02-24 15:25:51 -050022 os.path.join('out', 'Release_x64'),
Olli Etuahod39f8932015-12-17 17:10:02 +020023 os.path.join('out', 'Release'),
Jamie Madill1079bb22016-11-17 10:00:39 -080024 os.path.join('gyp', 'Release_x64'),
25 os.path.join('gyp', 'Release_Win32')
Olli Etuahod39f8932015-12-17 17:10:02 +020026]
Jamie Madilld6dfe672015-11-20 12:18:12 -050027metric = 'score'
28
Jamie Madille4857c72016-04-21 14:13:53 -040029# TODO(jmadill): Linux binaries
30binary_name = 'angle_perftests.exe'
31
Jamie Madilld6dfe672015-11-20 12:18:12 -050032scores = []
33
34# Danke to http://stackoverflow.com/a/27758326
35def mean(data):
36 """Return the sample arithmetic mean of data."""
37 n = len(data)
38 if n < 1:
39 raise ValueError('mean requires at least one data point')
40 return float(sum(data))/float(n) # in Python 2 use sum(data)/float(n)
41
42def _ss(data):
43 """Return sum of square deviations of sequence data."""
44 c = mean(data)
45 ss = sum((float(x)-c)**2 for x in data)
46 return ss
47
48def pstdev(data):
49 """Calculates the population standard deviation."""
50 n = len(data)
51 if n < 2:
52 raise ValueError('variance requires at least two data points')
53 ss = _ss(data)
54 pvar = ss/n # the population variance
55 return pvar**0.5
56
57def truncated_list(data, n):
58 """Compute a truncated list, n is truncation size"""
59 if len(data) < n * 2:
60 raise ValueError('list not large enough to truncate')
61 return sorted(data)[n:-n]
62
63def truncated_mean(data, n):
64 return mean(truncated_list(data, n))
65
66def truncated_stddev(data, n):
67 return pstdev(truncated_list(data, n))
68
Jamie Madille4857c72016-04-21 14:13:53 -040069# Find most recent binary
70newest_binary = None
71newest_mtime = None
Jamie Madilld6dfe672015-11-20 12:18:12 -050072
Jamie Madilld6dfe672015-11-20 12:18:12 -050073for path in perftests_paths:
Jamie Madille4857c72016-04-21 14:13:53 -040074 binary_path = os.path.join(base_path, path, binary_name)
Jamie Madille4857c72016-04-21 14:13:53 -040075 if os.path.exists(binary_path):
Jamie Madill1079bb22016-11-17 10:00:39 -080076 binary_mtime = os.path.getmtime(binary_path)
Jamie Madille4857c72016-04-21 14:13:53 -040077 if (newest_binary is None) or (binary_mtime > newest_mtime):
78 newest_binary = binary_path
79 newest_mtime = binary_mtime
80
81perftests_path = newest_binary
Jamie Madilld6dfe672015-11-20 12:18:12 -050082
Jamie Madill1079bb22016-11-17 10:00:39 -080083if perftests_path == None or not os.path.exists(perftests_path):
84 print("Cannot find Release angle_perftests.exe!")
Jamie Madilld6dfe672015-11-20 12:18:12 -050085 sys.exit(1)
86
87test_name = "DrawCallPerfBenchmark.Run/d3d11_null"
88
89if len(sys.argv) >= 2:
90 test_name = sys.argv[1]
91
Olli Etuaho967cb3b2015-12-17 18:37:16 +020092print('Using test executable: ' + perftests_path)
93print('Test name: ' + test_name)
94
Jamie Madilld6dfe672015-11-20 12:18:12 -050095# Infinite loop of running the tests.
96while True:
97 output = subprocess.check_output([perftests_path, '--gtest_filter=' + test_name])
98
99 start_index = output.find(metric + "=")
100 if start_index == -1:
Olli Etuahod39f8932015-12-17 17:10:02 +0200101 print("Did not find the score of the specified test in output:")
102 print(output)
Jamie Madilld6dfe672015-11-20 12:18:12 -0500103 sys.exit(1)
104
105 start_index += len(metric) + 2
106
107 end_index = output[start_index:].find(" ")
108 if end_index == -1:
Olli Etuahod39f8932015-12-17 17:10:02 +0200109 print("Error parsing output:")
110 print(output)
Jamie Madilld6dfe672015-11-20 12:18:12 -0500111 sys.exit(2)
112
Olli Etuahod39f8932015-12-17 17:10:02 +0200113 m = re.search('Running (\d+) tests', output)
114 if m and int(m.group(1)) > 1:
115 print("Found more than one test result in output:")
116 print(output)
117 sys.exit(3)
118
Jamie Madilld6dfe672015-11-20 12:18:12 -0500119 end_index += start_index
120
121 score = int(output[start_index:end_index])
122 sys.stdout.write("score: " + str(score))
123
124 scores.append(score)
125 sys.stdout.write(", mean: " + str(mean(scores)))
126
127 if (len(scores) > 1):
128 sys.stdout.write(", stddev: " + str(pstdev(scores)))
129
130 if (len(scores) > 7):
131 trucation_n = len(scores) >> 3
132 sys.stdout.write(", truncated mean: " + str(truncated_mean(scores, trucation_n)))
133 sys.stdout.write(", stddev: " + str(truncated_stddev(scores, trucation_n)))
134
135 print("")