| 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 |