| 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 |
| 11 The suite json format is expected to be: | 11 The suite json format is expected to be: |
| 12 { | 12 { |
| 13 "path": <relative path chunks to perf resources and main file>, | 13 "path": <relative path chunks to perf resources and main file>, |
| 14 "name": <optional suite name, file name is default>, | 14 "name": <optional suite name, file name is default>, |
| 15 "archs": [<architecture name for which this suite is run>, ...], | 15 "archs": [<architecture name for which this suite is run>, ...], |
| 16 "binary": <name of binary to run, default "d8">, | 16 "binary": <name of binary to run, default "d8">, |
| 17 "flags": [<flag to d8>, ...], | 17 "flags": [<flag to d8>, ...], |
| 18 "test_flags": [<flag to the test file>, ...], |
| 18 "run_count": <how often will this suite run (optional)>, | 19 "run_count": <how often will this suite run (optional)>, |
| 19 "run_count_XXX": <how often will this suite run for arch XXX (optional)>, | 20 "run_count_XXX": <how often will this suite run for arch XXX (optional)>, |
| 20 "resources": [<js file to be loaded before main>, ...] | 21 "resources": [<js file to be loaded before main>, ...] |
| 21 "main": <main js perf runner file>, | 22 "main": <main js perf runner file>, |
| 22 "results_regexp": <optional regexp>, | 23 "results_regexp": <optional regexp>, |
| 23 "results_processor": <optional python results processor script>, | 24 "results_processor": <optional python results processor script>, |
| 24 "units": <the unit specification for the performance dashboard>, | 25 "units": <the unit specification for the performance dashboard>, |
| 25 "tests": [ | 26 "tests": [ |
| 26 { | 27 { |
| 27 "name": <name of the trace>, | 28 "name": <name of the trace>, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 47 | 48 |
| 48 The <output> is a temporary file containing d8 output. The results_regexp will | 49 The <output> is a temporary file containing d8 output. The results_regexp will |
| 49 be applied to the output of this script. | 50 be applied to the output of this script. |
| 50 | 51 |
| 51 A suite without "tests" is considered a performance test itself. | 52 A suite without "tests" is considered a performance test itself. |
| 52 | 53 |
| 53 Full example (suite with one runner): | 54 Full example (suite with one runner): |
| 54 { | 55 { |
| 55 "path": ["."], | 56 "path": ["."], |
| 56 "flags": ["--expose-gc"], | 57 "flags": ["--expose-gc"], |
| 58 "test_flags": ["5"], |
| 57 "archs": ["ia32", "x64"], | 59 "archs": ["ia32", "x64"], |
| 58 "run_count": 5, | 60 "run_count": 5, |
| 59 "run_count_ia32": 3, | 61 "run_count_ia32": 3, |
| 60 "main": "run.js", | 62 "main": "run.js", |
| 61 "results_regexp": "^%s: (.+)$", | 63 "results_regexp": "^%s: (.+)$", |
| 62 "units": "score", | 64 "units": "score", |
| 63 "tests": [ | 65 "tests": [ |
| 64 {"name": "Richards"}, | 66 {"name": "Richards"}, |
| 65 {"name": "DeltaBlue"}, | 67 {"name": "DeltaBlue"}, |
| 66 {"name": "NavierStokes", | 68 {"name": "NavierStokes", |
| (...skipping 15 matching lines...) Expand all Loading... |
| 82 "run_count": 3, | 84 "run_count": 3, |
| 83 "results_regexp": "^Richards: (.+)$"}, | 85 "results_regexp": "^Richards: (.+)$"}, |
| 84 {"name": "NavierStokes", | 86 {"name": "NavierStokes", |
| 85 "path": ["navier_stokes"], | 87 "path": ["navier_stokes"], |
| 86 "main": "run.js", | 88 "main": "run.js", |
| 87 "results_regexp": "^NavierStokes: (.+)$"} | 89 "results_regexp": "^NavierStokes: (.+)$"} |
| 88 ] | 90 ] |
| 89 } | 91 } |
| 90 | 92 |
| 91 Path pieces are concatenated. D8 is always run with the suite's path as cwd. | 93 Path pieces are concatenated. D8 is always run with the suite's path as cwd. |
| 94 |
| 95 The test flags are passed to the js test file after '--'. |
| 92 """ | 96 """ |
| 93 | 97 |
| 94 from collections import OrderedDict | 98 from collections import OrderedDict |
| 95 import json | 99 import json |
| 96 import math | 100 import math |
| 97 import optparse | 101 import optparse |
| 98 import os | 102 import os |
| 99 import re | 103 import re |
| 100 import sys | 104 import sys |
| 101 | 105 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 class DefaultSentinel(Node): | 168 class DefaultSentinel(Node): |
| 165 """Fake parent node with all default values.""" | 169 """Fake parent node with all default values.""" |
| 166 def __init__(self): | 170 def __init__(self): |
| 167 super(DefaultSentinel, self).__init__() | 171 super(DefaultSentinel, self).__init__() |
| 168 self.binary = "d8" | 172 self.binary = "d8" |
| 169 self.run_count = 10 | 173 self.run_count = 10 |
| 170 self.timeout = 60 | 174 self.timeout = 60 |
| 171 self.path = [] | 175 self.path = [] |
| 172 self.graphs = [] | 176 self.graphs = [] |
| 173 self.flags = [] | 177 self.flags = [] |
| 178 self.test_flags = [] |
| 174 self.resources = [] | 179 self.resources = [] |
| 175 self.results_regexp = None | 180 self.results_regexp = None |
| 176 self.stddev_regexp = None | 181 self.stddev_regexp = None |
| 177 self.units = "score" | 182 self.units = "score" |
| 178 self.total = False | 183 self.total = False |
| 179 | 184 |
| 180 | 185 |
| 181 class Graph(Node): | 186 class Graph(Node): |
| 182 """Represents a suite definition. | 187 """Represents a suite definition. |
| 183 | 188 |
| 184 Can either be a leaf or an inner node that provides default values. | 189 Can either be a leaf or an inner node that provides default values. |
| 185 """ | 190 """ |
| 186 def __init__(self, suite, parent, arch): | 191 def __init__(self, suite, parent, arch): |
| 187 super(Graph, self).__init__() | 192 super(Graph, self).__init__() |
| 188 self._suite = suite | 193 self._suite = suite |
| 189 | 194 |
| 190 assert isinstance(suite.get("path", []), list) | 195 assert isinstance(suite.get("path", []), list) |
| 191 assert isinstance(suite["name"], basestring) | 196 assert isinstance(suite["name"], basestring) |
| 192 assert isinstance(suite.get("flags", []), list) | 197 assert isinstance(suite.get("flags", []), list) |
| 198 assert isinstance(suite.get("test_flags", []), list) |
| 193 assert isinstance(suite.get("resources", []), list) | 199 assert isinstance(suite.get("resources", []), list) |
| 194 | 200 |
| 195 # Accumulated values. | 201 # Accumulated values. |
| 196 self.path = parent.path[:] + suite.get("path", []) | 202 self.path = parent.path[:] + suite.get("path", []) |
| 197 self.graphs = parent.graphs[:] + [suite["name"]] | 203 self.graphs = parent.graphs[:] + [suite["name"]] |
| 198 self.flags = parent.flags[:] + suite.get("flags", []) | 204 self.flags = parent.flags[:] + suite.get("flags", []) |
| 205 self.test_flags = parent.test_flags[:] + suite.get("test_flags", []) |
| 199 self.resources = parent.resources[:] + suite.get("resources", []) | 206 self.resources = parent.resources[:] + suite.get("resources", []) |
| 200 | 207 |
| 201 # Descrete values (with parent defaults). | 208 # Descrete values (with parent defaults). |
| 202 self.binary = suite.get("binary", parent.binary) | 209 self.binary = suite.get("binary", parent.binary) |
| 203 self.run_count = suite.get("run_count", parent.run_count) | 210 self.run_count = suite.get("run_count", parent.run_count) |
| 204 self.run_count = suite.get("run_count_%s" % arch, self.run_count) | 211 self.run_count = suite.get("run_count_%s" % arch, self.run_count) |
| 205 self.timeout = suite.get("timeout", parent.timeout) | 212 self.timeout = suite.get("timeout", parent.timeout) |
| 206 self.units = suite.get("units", parent.units) | 213 self.units = suite.get("units", parent.units) |
| 207 self.total = suite.get("total", parent.total) | 214 self.total = suite.get("total", parent.total) |
| 208 | 215 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 """Changes the cwd to to path defined in the current graph. | 282 """Changes the cwd to to path defined in the current graph. |
| 276 | 283 |
| 277 The tests are supposed to be relative to the suite configuration. | 284 The tests are supposed to be relative to the suite configuration. |
| 278 """ | 285 """ |
| 279 suite_dir = os.path.abspath(os.path.dirname(suite_path)) | 286 suite_dir = os.path.abspath(os.path.dirname(suite_path)) |
| 280 bench_dir = os.path.normpath(os.path.join(*self.path)) | 287 bench_dir = os.path.normpath(os.path.join(*self.path)) |
| 281 os.chdir(os.path.join(suite_dir, bench_dir)) | 288 os.chdir(os.path.join(suite_dir, bench_dir)) |
| 282 | 289 |
| 283 def GetCommand(self, shell_dir): | 290 def GetCommand(self, shell_dir): |
| 284 # TODO(machenbach): This requires +.exe if run on windows. | 291 # TODO(machenbach): This requires +.exe if run on windows. |
| 292 suffix = ["--"] + self.test_flags if self.test_flags else [] |
| 285 return ( | 293 return ( |
| 286 [os.path.join(shell_dir, self.binary)] + | 294 [os.path.join(shell_dir, self.binary)] + |
| 287 self.flags + | 295 self.flags + |
| 288 self.resources + | 296 self.resources + |
| 289 [self.main] | 297 [self.main] + |
| 298 suffix |
| 290 ) | 299 ) |
| 291 | 300 |
| 292 def Run(self, runner): | 301 def Run(self, runner): |
| 293 """Iterates over several runs and handles the output for all traces.""" | 302 """Iterates over several runs and handles the output for all traces.""" |
| 294 for stdout in runner(): | 303 for stdout in runner(): |
| 295 for trace in self._children: | 304 for trace in self._children: |
| 296 trace.ConsumeOutput(stdout) | 305 trace.ConsumeOutput(stdout) |
| 297 res = reduce(lambda r, t: r + t.GetResults(), self._children, Results()) | 306 res = reduce(lambda r, t: r + t.GetResults(), self._children, Results()) |
| 298 | 307 |
| 299 if not res.traces or not self.total: | 308 if not res.traces or not self.total: |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 | 508 |
| 500 if options.json_test_results: | 509 if options.json_test_results: |
| 501 results.WriteToFile(options.json_test_results) | 510 results.WriteToFile(options.json_test_results) |
| 502 else: # pragma: no cover | 511 else: # pragma: no cover |
| 503 print results | 512 print results |
| 504 | 513 |
| 505 return min(1, len(results.errors)) | 514 return min(1, len(results.errors)) |
| 506 | 515 |
| 507 if __name__ == "__main__": # pragma: no cover | 516 if __name__ == "__main__": # pragma: no cover |
| 508 sys.exit(Main(sys.argv[1:])) | 517 sys.exit(Main(sys.argv[1:])) |
| OLD | NEW |