Jamie Madill | d6dfe67 | 2015-11-20 12:18:12 -0500 | [diff] [blame] | 1 | #!/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 | |
| 13 | import subprocess |
| 14 | import sys |
| 15 | import os |
| 16 | |
| 17 | # You might have to re-order these to find the specific version you want. |
| 18 | perftests_paths = ['out/Release', 'build/Release_x64', 'build/Release_Win32'] |
| 19 | metric = 'score' |
| 20 | |
| 21 | scores = [] |
| 22 | |
| 23 | # Danke to http://stackoverflow.com/a/27758326 |
| 24 | def mean(data): |
| 25 | """Return the sample arithmetic mean of data.""" |
| 26 | n = len(data) |
| 27 | if n < 1: |
| 28 | raise ValueError('mean requires at least one data point') |
| 29 | return float(sum(data))/float(n) # in Python 2 use sum(data)/float(n) |
| 30 | |
| 31 | def _ss(data): |
| 32 | """Return sum of square deviations of sequence data.""" |
| 33 | c = mean(data) |
| 34 | ss = sum((float(x)-c)**2 for x in data) |
| 35 | return ss |
| 36 | |
| 37 | def pstdev(data): |
| 38 | """Calculates the population standard deviation.""" |
| 39 | n = len(data) |
| 40 | if n < 2: |
| 41 | raise ValueError('variance requires at least two data points') |
| 42 | ss = _ss(data) |
| 43 | pvar = ss/n # the population variance |
| 44 | return pvar**0.5 |
| 45 | |
| 46 | def truncated_list(data, n): |
| 47 | """Compute a truncated list, n is truncation size""" |
| 48 | if len(data) < n * 2: |
| 49 | raise ValueError('list not large enough to truncate') |
| 50 | return sorted(data)[n:-n] |
| 51 | |
| 52 | def truncated_mean(data, n): |
| 53 | return mean(truncated_list(data, n)) |
| 54 | |
| 55 | def truncated_stddev(data, n): |
| 56 | return pstdev(truncated_list(data, n)) |
| 57 | |
| 58 | perftests_path = "" |
| 59 | |
| 60 | # TODO(jmadill): Linux binaries |
| 61 | for path in perftests_paths: |
| 62 | perftests_path = os.path.join(path, 'angle_perftests.exe') |
| 63 | if os.path.exists(perftests_path): |
| 64 | break |
| 65 | |
| 66 | if not os.path.exists(perftests_path): |
| 67 | print("Cannot find angle_perftests.exe!") |
| 68 | sys.exit(1) |
| 69 | |
| 70 | test_name = "DrawCallPerfBenchmark.Run/d3d11_null" |
| 71 | |
| 72 | if len(sys.argv) >= 2: |
| 73 | test_name = sys.argv[1] |
| 74 | |
| 75 | # Infinite loop of running the tests. |
| 76 | while True: |
| 77 | output = subprocess.check_output([perftests_path, '--gtest_filter=' + test_name]) |
| 78 | |
| 79 | start_index = output.find(metric + "=") |
| 80 | if start_index == -1: |
| 81 | print("Did not find test output") |
| 82 | sys.exit(1) |
| 83 | |
| 84 | start_index += len(metric) + 2 |
| 85 | |
| 86 | end_index = output[start_index:].find(" ") |
| 87 | if end_index == -1: |
| 88 | print("Error parsing output") |
| 89 | sys.exit(2) |
| 90 | |
| 91 | end_index += start_index |
| 92 | |
| 93 | score = int(output[start_index:end_index]) |
| 94 | sys.stdout.write("score: " + str(score)) |
| 95 | |
| 96 | scores.append(score) |
| 97 | sys.stdout.write(", mean: " + str(mean(scores))) |
| 98 | |
| 99 | if (len(scores) > 1): |
| 100 | sys.stdout.write(", stddev: " + str(pstdev(scores))) |
| 101 | |
| 102 | if (len(scores) > 7): |
| 103 | trucation_n = len(scores) >> 3 |
| 104 | sys.stdout.write(", truncated mean: " + str(truncated_mean(scores, trucation_n))) |
| 105 | sys.stdout.write(", stddev: " + str(truncated_stddev(scores, trucation_n))) |
| 106 | |
| 107 | print("") |