OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 the V8 project authors. All rights reserved. | 2 # Copyright 2014 the V8 project authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """ | 6 """ |
7 Performance runner for d8. | 7 Performance runner for d8. |
8 | 8 |
9 Call e.g. with tools/run-perf.py --arch ia32 some_suite.json | 9 Call e.g. with tools/run-perf.py --arch ia32 some_suite.json |
10 | 10 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 {"name": "NavierStokes", | 84 {"name": "NavierStokes", |
85 "path": ["navier_stokes"], | 85 "path": ["navier_stokes"], |
86 "main": "run.js", | 86 "main": "run.js", |
87 "results_regexp": "^NavierStokes: (.+)$"} | 87 "results_regexp": "^NavierStokes: (.+)$"} |
88 ] | 88 ] |
89 } | 89 } |
90 | 90 |
91 Path pieces are concatenated. D8 is always run with the suite's path as cwd. | 91 Path pieces are concatenated. D8 is always run with the suite's path as cwd. |
92 """ | 92 """ |
93 | 93 |
| 94 from collections import OrderedDict |
94 import json | 95 import json |
95 import math | 96 import math |
96 import optparse | 97 import optparse |
97 import os | 98 import os |
98 import re | 99 import re |
99 import sys | 100 import sys |
100 | 101 |
101 from testrunner.local import commands | 102 from testrunner.local import commands |
102 from testrunner.local import utils | 103 from testrunner.local import utils |
103 | 104 |
104 ARCH_GUESS = utils.DefaultArch() | 105 ARCH_GUESS = utils.DefaultArch() |
105 SUPPORTED_ARCHS = ["android_arm", | 106 SUPPORTED_ARCHS = ["android_arm", |
106 "android_arm64", | 107 "android_arm64", |
107 "android_ia32", | 108 "android_ia32", |
108 "arm", | 109 "arm", |
109 "ia32", | 110 "ia32", |
110 "mips", | 111 "mips", |
111 "mipsel", | 112 "mipsel", |
112 "nacl_ia32", | 113 "nacl_ia32", |
113 "nacl_x64", | 114 "nacl_x64", |
114 "x64", | 115 "x64", |
115 "arm64"] | 116 "arm64"] |
116 | 117 |
117 GENERIC_RESULTS_RE = re.compile( | 118 GENERIC_RESULTS_RE = re.compile(r"^RESULT ([^:]+): ([^=]+)= ([^ ]+) ([^ ]*)$") |
118 r"^Trace\(([^\)]+)\), Result\(([^\)]+)\), StdDev\(([^\)]+)\)$") | 119 RESULT_STDDEV_RE = re.compile(r"^\{([^\}]+)\}$") |
| 120 RESULT_LIST_RE = re.compile(r"^\[([^\]]+)\]$") |
| 121 |
119 | 122 |
120 | 123 |
121 def GeometricMean(values): | 124 def GeometricMean(values): |
122 """Returns the geometric mean of a list of values. | 125 """Returns the geometric mean of a list of values. |
123 | 126 |
124 The mean is calculated using log to avoid overflow. | 127 The mean is calculated using log to avoid overflow. |
125 """ | 128 """ |
126 values = map(float, values) | 129 values = map(float, values) |
127 return str(math.exp(sum(map(math.log, values)) / len(values))) | 130 return str(math.exp(sum(map(math.log, values)) / len(values))) |
128 | 131 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 return self.GetResults() | 330 return self.GetResults() |
328 | 331 |
329 | 332 |
330 class RunnableGeneric(Runnable): | 333 class RunnableGeneric(Runnable): |
331 """Represents a runnable suite definition with generic traces.""" | 334 """Represents a runnable suite definition with generic traces.""" |
332 def __init__(self, suite, parent, arch): | 335 def __init__(self, suite, parent, arch): |
333 super(RunnableGeneric, self).__init__(suite, parent, arch) | 336 super(RunnableGeneric, self).__init__(suite, parent, arch) |
334 | 337 |
335 def Run(self, runner): | 338 def Run(self, runner): |
336 """Iterates over several runs and handles the output.""" | 339 """Iterates over several runs and handles the output.""" |
337 traces = {} | 340 traces = OrderedDict() |
338 for stdout in runner(): | 341 for stdout in runner(): |
339 for line in stdout.strip().splitlines(): | 342 for line in stdout.strip().splitlines(): |
340 match = GENERIC_RESULTS_RE.match(line) | 343 match = GENERIC_RESULTS_RE.match(line) |
341 if match: | 344 if match: |
342 trace = match.group(1) | 345 stddev = "" |
343 result = match.group(2) | 346 graph = match.group(1) |
344 stddev = match.group(3) | 347 trace = match.group(2) |
| 348 body = match.group(3) |
| 349 units = match.group(4) |
| 350 match_stddev = RESULT_STDDEV_RE.match(body) |
| 351 match_list = RESULT_LIST_RE.match(body) |
| 352 if match_stddev: |
| 353 result, stddev = map(str.strip, match_stddev.group(1).split(",")) |
| 354 results = [result] |
| 355 elif match_list: |
| 356 results = map(str.strip, match_list.group(1).split(",")) |
| 357 else: |
| 358 results = [body.strip()] |
| 359 |
345 trace_result = traces.setdefault(trace, Results([{ | 360 trace_result = traces.setdefault(trace, Results([{ |
346 "graphs": self.graphs + [trace], | 361 "graphs": self.graphs + [graph, trace], |
347 "units": self.units, | 362 "units": (units or self.units).strip(), |
348 "results": [], | 363 "results": [], |
349 "stddev": "", | 364 "stddev": "", |
350 }], [])) | 365 }], [])) |
351 trace_result.traces[0]["results"].append(result) | 366 trace_result.traces[0]["results"].extend(results) |
352 trace_result.traces[0]["stddev"] = stddev | 367 trace_result.traces[0]["stddev"] = stddev |
353 | 368 |
354 return reduce(lambda r, t: r + t, traces.itervalues(), Results()) | 369 return reduce(lambda r, t: r + t, traces.itervalues(), Results()) |
355 | 370 |
356 | 371 |
357 def MakeGraph(suite, arch, parent): | 372 def MakeGraph(suite, arch, parent): |
358 """Factory method for making graph objects.""" | 373 """Factory method for making graph objects.""" |
359 if isinstance(parent, Runnable): | 374 if isinstance(parent, Runnable): |
360 # Below a runnable can only be traces. | 375 # Below a runnable can only be traces. |
361 return Trace(suite, parent, arch) | 376 return Trace(suite, parent, arch) |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 | 499 |
485 if options.json_test_results: | 500 if options.json_test_results: |
486 results.WriteToFile(options.json_test_results) | 501 results.WriteToFile(options.json_test_results) |
487 else: # pragma: no cover | 502 else: # pragma: no cover |
488 print results | 503 print results |
489 | 504 |
490 return min(1, len(results.errors)) | 505 return min(1, len(results.errors)) |
491 | 506 |
492 if __name__ == "__main__": # pragma: no cover | 507 if __name__ == "__main__": # pragma: no cover |
493 sys.exit(Main(sys.argv[1:])) | 508 sys.exit(Main(sys.argv[1:])) |
OLD | NEW |