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 |