| 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 from collections import namedtuple | 6 from collections import namedtuple |
| 7 import coverage | 7 import coverage |
| 8 import json | 8 import json |
| 9 from mock import DEFAULT | 9 from mock import DEFAULT |
| 10 from mock import MagicMock | 10 from mock import MagicMock |
| 11 import os | 11 import os |
| 12 from os import path, sys | 12 from os import path, sys |
| 13 import shutil | 13 import shutil |
| 14 import tempfile | 14 import tempfile |
| 15 import unittest | 15 import unittest |
| 16 | 16 |
| 17 # Requires python-coverage and python-mock. Native python coverage | 17 # Requires python-coverage and python-mock. Native python coverage |
| 18 # version >= 3.7.1 should be installed to get the best speed. | 18 # version >= 3.7.1 should be installed to get the best speed. |
| 19 | 19 |
| 20 TEST_WORKSPACE = path.join(tempfile.gettempdir(), "test-v8-run-benchmarks") | 20 TEST_WORKSPACE = path.join(tempfile.gettempdir(), "test-v8-run-perf") |
| 21 | 21 |
| 22 V8_JSON = { | 22 V8_JSON = { |
| 23 "path": ["."], | 23 "path": ["."], |
| 24 "binary": "d7", | 24 "binary": "d7", |
| 25 "flags": ["--flag"], | 25 "flags": ["--flag"], |
| 26 "main": "run.js", | 26 "main": "run.js", |
| 27 "run_count": 1, | 27 "run_count": 1, |
| 28 "results_regexp": "^%s: (.+)$", | 28 "results_regexp": "^%s: (.+)$", |
| 29 "benchmarks": [ | 29 "tests": [ |
| 30 {"name": "Richards"}, | 30 {"name": "Richards"}, |
| 31 {"name": "DeltaBlue"}, | 31 {"name": "DeltaBlue"}, |
| 32 ] | 32 ] |
| 33 } | 33 } |
| 34 | 34 |
| 35 V8_NESTED_SUITES_JSON = { | 35 V8_NESTED_SUITES_JSON = { |
| 36 "path": ["."], | 36 "path": ["."], |
| 37 "flags": ["--flag"], | 37 "flags": ["--flag"], |
| 38 "run_count": 1, | 38 "run_count": 1, |
| 39 "units": "score", | 39 "units": "score", |
| 40 "benchmarks": [ | 40 "tests": [ |
| 41 {"name": "Richards", | 41 {"name": "Richards", |
| 42 "path": ["richards"], | 42 "path": ["richards"], |
| 43 "binary": "d7", | 43 "binary": "d7", |
| 44 "main": "run.js", | 44 "main": "run.js", |
| 45 "resources": ["file1.js", "file2.js"], | 45 "resources": ["file1.js", "file2.js"], |
| 46 "run_count": 2, | 46 "run_count": 2, |
| 47 "results_regexp": "^Richards: (.+)$"}, | 47 "results_regexp": "^Richards: (.+)$"}, |
| 48 {"name": "Sub", | 48 {"name": "Sub", |
| 49 "path": ["sub"], | 49 "path": ["sub"], |
| 50 "benchmarks": [ | 50 "tests": [ |
| 51 {"name": "Leaf", | 51 {"name": "Leaf", |
| 52 "path": ["leaf"], | 52 "path": ["leaf"], |
| 53 "run_count_x64": 3, | 53 "run_count_x64": 3, |
| 54 "units": "ms", | 54 "units": "ms", |
| 55 "main": "run.js", | 55 "main": "run.js", |
| 56 "results_regexp": "^Simple: (.+) ms.$"}, | 56 "results_regexp": "^Simple: (.+) ms.$"}, |
| 57 ] | 57 ] |
| 58 }, | 58 }, |
| 59 {"name": "DeltaBlue", | 59 {"name": "DeltaBlue", |
| 60 "path": ["delta_blue"], | 60 "path": ["delta_blue"], |
| (...skipping 11 matching lines...) Expand all Loading... |
| 72 "path": ["."], | 72 "path": ["."], |
| 73 "binary": "cc", | 73 "binary": "cc", |
| 74 "flags": ["--flag"], | 74 "flags": ["--flag"], |
| 75 "generic": True, | 75 "generic": True, |
| 76 "run_count": 1, | 76 "run_count": 1, |
| 77 "units": "ms", | 77 "units": "ms", |
| 78 } | 78 } |
| 79 | 79 |
| 80 Output = namedtuple("Output", "stdout, stderr") | 80 Output = namedtuple("Output", "stdout, stderr") |
| 81 | 81 |
| 82 class BenchmarksTest(unittest.TestCase): | 82 class PerfTest(unittest.TestCase): |
| 83 @classmethod | 83 @classmethod |
| 84 def setUpClass(cls): | 84 def setUpClass(cls): |
| 85 cls.base = path.dirname(path.dirname(path.abspath(__file__))) | 85 cls.base = path.dirname(path.dirname(path.abspath(__file__))) |
| 86 sys.path.append(cls.base) | 86 sys.path.append(cls.base) |
| 87 cls._cov = coverage.coverage( | 87 cls._cov = coverage.coverage( |
| 88 include=([os.path.join(cls.base, "run_benchmarks.py")])) | 88 include=([os.path.join(cls.base, "run_perf.py")])) |
| 89 cls._cov.start() | 89 cls._cov.start() |
| 90 import run_benchmarks | 90 import run_perf |
| 91 from testrunner.local import commands | 91 from testrunner.local import commands |
| 92 global commands | 92 global commands |
| 93 global run_benchmarks | 93 global run_perf |
| 94 | 94 |
| 95 @classmethod | 95 @classmethod |
| 96 def tearDownClass(cls): | 96 def tearDownClass(cls): |
| 97 cls._cov.stop() | 97 cls._cov.stop() |
| 98 print "" | 98 print "" |
| 99 print cls._cov.report() | 99 print cls._cov.report() |
| 100 | 100 |
| 101 def setUp(self): | 101 def setUp(self): |
| 102 self.maxDiff = None | 102 self.maxDiff = None |
| 103 if path.exists(TEST_WORKSPACE): | 103 if path.exists(TEST_WORKSPACE): |
| 104 shutil.rmtree(TEST_WORKSPACE) | 104 shutil.rmtree(TEST_WORKSPACE) |
| 105 os.makedirs(TEST_WORKSPACE) | 105 os.makedirs(TEST_WORKSPACE) |
| 106 | 106 |
| 107 def tearDown(self): | 107 def tearDown(self): |
| 108 if path.exists(TEST_WORKSPACE): | 108 if path.exists(TEST_WORKSPACE): |
| 109 shutil.rmtree(TEST_WORKSPACE) | 109 shutil.rmtree(TEST_WORKSPACE) |
| 110 | 110 |
| 111 def _WriteTestInput(self, json_content): | 111 def _WriteTestInput(self, json_content): |
| 112 self._test_input = path.join(TEST_WORKSPACE, "test.json") | 112 self._test_input = path.join(TEST_WORKSPACE, "test.json") |
| 113 with open(self._test_input, "w") as f: | 113 with open(self._test_input, "w") as f: |
| 114 f.write(json.dumps(json_content)) | 114 f.write(json.dumps(json_content)) |
| 115 | 115 |
| 116 def _MockCommand(self, *args): | 116 def _MockCommand(self, *args): |
| 117 # Fake output for each benchmark run. | 117 # Fake output for each test run. |
| 118 benchmark_outputs = [Output(stdout=arg, stderr=None) for arg in args[1]] | 118 test_outputs = [Output(stdout=arg, stderr=None) for arg in args[1]] |
| 119 def execute(*args, **kwargs): | 119 def execute(*args, **kwargs): |
| 120 return benchmark_outputs.pop() | 120 return test_outputs.pop() |
| 121 commands.Execute = MagicMock(side_effect=execute) | 121 commands.Execute = MagicMock(side_effect=execute) |
| 122 | 122 |
| 123 # Check that d8 is called from the correct cwd for each benchmark run. | 123 # Check that d8 is called from the correct cwd for each test run. |
| 124 dirs = [path.join(TEST_WORKSPACE, arg) for arg in args[0]] | 124 dirs = [path.join(TEST_WORKSPACE, arg) for arg in args[0]] |
| 125 def chdir(*args, **kwargs): | 125 def chdir(*args, **kwargs): |
| 126 self.assertEquals(dirs.pop(), args[0]) | 126 self.assertEquals(dirs.pop(), args[0]) |
| 127 os.chdir = MagicMock(side_effect=chdir) | 127 os.chdir = MagicMock(side_effect=chdir) |
| 128 | 128 |
| 129 def _CallMain(self, *args): | 129 def _CallMain(self, *args): |
| 130 self._test_output = path.join(TEST_WORKSPACE, "results.json") | 130 self._test_output = path.join(TEST_WORKSPACE, "results.json") |
| 131 all_args=[ | 131 all_args=[ |
| 132 "--json-test-results", | 132 "--json-test-results", |
| 133 self._test_output, | 133 self._test_output, |
| 134 self._test_input, | 134 self._test_input, |
| 135 ] | 135 ] |
| 136 all_args += args | 136 all_args += args |
| 137 return run_benchmarks.Main(all_args) | 137 return run_perf.Main(all_args) |
| 138 | 138 |
| 139 def _LoadResults(self): | 139 def _LoadResults(self): |
| 140 with open(self._test_output) as f: | 140 with open(self._test_output) as f: |
| 141 return json.load(f) | 141 return json.load(f) |
| 142 | 142 |
| 143 def _VerifyResults(self, suite, units, traces): | 143 def _VerifyResults(self, suite, units, traces): |
| 144 self.assertEquals([ | 144 self.assertEquals([ |
| 145 {"units": units, | 145 {"units": units, |
| 146 "graphs": [suite, trace["name"]], | 146 "graphs": [suite, trace["name"]], |
| 147 "results": trace["results"], | 147 "results": trace["results"], |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 {"name": "Richards", "results": ["50", "100"], "stddev": ""}, | 189 {"name": "Richards", "results": ["50", "100"], "stddev": ""}, |
| 190 {"name": "DeltaBlue", "results": ["300", "200"], "stddev": ""}, | 190 {"name": "DeltaBlue", "results": ["300", "200"], "stddev": ""}, |
| 191 ]) | 191 ]) |
| 192 self._VerifyErrors([]) | 192 self._VerifyErrors([]) |
| 193 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js") | 193 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js") |
| 194 | 194 |
| 195 def testTwoRuns_SubRegexp(self): | 195 def testTwoRuns_SubRegexp(self): |
| 196 test_input = dict(V8_JSON) | 196 test_input = dict(V8_JSON) |
| 197 test_input["run_count"] = 2 | 197 test_input["run_count"] = 2 |
| 198 del test_input["results_regexp"] | 198 del test_input["results_regexp"] |
| 199 test_input["benchmarks"][0]["results_regexp"] = "^Richards: (.+)$" | 199 test_input["tests"][0]["results_regexp"] = "^Richards: (.+)$" |
| 200 test_input["benchmarks"][1]["results_regexp"] = "^DeltaBlue: (.+)$" | 200 test_input["tests"][1]["results_regexp"] = "^DeltaBlue: (.+)$" |
| 201 self._WriteTestInput(test_input) | 201 self._WriteTestInput(test_input) |
| 202 self._MockCommand([".", "."], | 202 self._MockCommand([".", "."], |
| 203 ["Richards: 100\nDeltaBlue: 200\n", | 203 ["Richards: 100\nDeltaBlue: 200\n", |
| 204 "Richards: 50\nDeltaBlue: 300\n"]) | 204 "Richards: 50\nDeltaBlue: 300\n"]) |
| 205 self.assertEquals(0, self._CallMain()) | 205 self.assertEquals(0, self._CallMain()) |
| 206 self._VerifyResults("test", "score", [ | 206 self._VerifyResults("test", "score", [ |
| 207 {"name": "Richards", "results": ["50", "100"], "stddev": ""}, | 207 {"name": "Richards", "results": ["50", "100"], "stddev": ""}, |
| 208 {"name": "DeltaBlue", "results": ["300", "200"], "stddev": ""}, | 208 {"name": "DeltaBlue", "results": ["300", "200"], "stddev": ""}, |
| 209 ]) | 209 ]) |
| 210 self._VerifyErrors([]) | 210 self._VerifyErrors([]) |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 self._MockCommand(["."], ["Richards: 3\nRichards-stddev: 0.7\n" | 267 self._MockCommand(["."], ["Richards: 3\nRichards-stddev: 0.7\n" |
| 268 "DeltaBlue: 6\nDeltaBlue-boom: 0.9\n", | 268 "DeltaBlue: 6\nDeltaBlue-boom: 0.9\n", |
| 269 "Richards: 2\nRichards-stddev: 0.5\n" | 269 "Richards: 2\nRichards-stddev: 0.5\n" |
| 270 "DeltaBlue: 5\nDeltaBlue-stddev: 0.8\n"]) | 270 "DeltaBlue: 5\nDeltaBlue-stddev: 0.8\n"]) |
| 271 self.assertEquals(1, self._CallMain()) | 271 self.assertEquals(1, self._CallMain()) |
| 272 self._VerifyResults("test", "score", [ | 272 self._VerifyResults("test", "score", [ |
| 273 {"name": "Richards", "results": ["2", "3"], "stddev": "0.7"}, | 273 {"name": "Richards", "results": ["2", "3"], "stddev": "0.7"}, |
| 274 {"name": "DeltaBlue", "results": ["5", "6"], "stddev": "0.8"}, | 274 {"name": "DeltaBlue", "results": ["5", "6"], "stddev": "0.8"}, |
| 275 ]) | 275 ]) |
| 276 self._VerifyErrors( | 276 self._VerifyErrors( |
| 277 ["Benchmark Richards should only run once since a stddev is provided " | 277 ["Test Richards should only run once since a stddev is provided " |
| 278 "by the benchmark.", | 278 "by the test.", |
| 279 "Benchmark DeltaBlue should only run once since a stddev is provided " | 279 "Test DeltaBlue should only run once since a stddev is provided " |
| 280 "by the benchmark.", | 280 "by the test.", |
| 281 "Regexp \"^DeltaBlue\-stddev: (.+)$\" didn't match for benchmark " | 281 "Regexp \"^DeltaBlue\-stddev: (.+)$\" didn't match for test " |
| 282 "DeltaBlue."]) | 282 "DeltaBlue."]) |
| 283 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js") | 283 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js") |
| 284 | 284 |
| 285 def testBuildbot(self): | 285 def testBuildbot(self): |
| 286 self._WriteTestInput(V8_JSON) | 286 self._WriteTestInput(V8_JSON) |
| 287 self._MockCommand(["."], ["Richards: 1.234\nDeltaBlue: 10657567\n"]) | 287 self._MockCommand(["."], ["Richards: 1.234\nDeltaBlue: 10657567\n"]) |
| 288 self.assertEquals(0, self._CallMain("--buildbot")) | 288 self.assertEquals(0, self._CallMain("--buildbot")) |
| 289 self._VerifyResults("test", "score", [ | 289 self._VerifyResults("test", "score", [ |
| 290 {"name": "Richards", "results": ["1.234"], "stddev": ""}, | 290 {"name": "Richards", "results": ["1.234"], "stddev": ""}, |
| 291 {"name": "DeltaBlue", "results": ["10657567"], "stddev": ""}, | 291 {"name": "DeltaBlue", "results": ["10657567"], "stddev": ""}, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 311 test_input = dict(V8_JSON) | 311 test_input = dict(V8_JSON) |
| 312 test_input["total"] = True | 312 test_input["total"] = True |
| 313 self._WriteTestInput(test_input) | 313 self._WriteTestInput(test_input) |
| 314 self._MockCommand(["."], ["x\nRichaards: 1.234\nDeltaBlue: 10657567\ny\n"]) | 314 self._MockCommand(["."], ["x\nRichaards: 1.234\nDeltaBlue: 10657567\ny\n"]) |
| 315 self.assertEquals(1, self._CallMain("--buildbot")) | 315 self.assertEquals(1, self._CallMain("--buildbot")) |
| 316 self._VerifyResults("test", "score", [ | 316 self._VerifyResults("test", "score", [ |
| 317 {"name": "Richards", "results": [], "stddev": ""}, | 317 {"name": "Richards", "results": [], "stddev": ""}, |
| 318 {"name": "DeltaBlue", "results": ["10657567"], "stddev": ""}, | 318 {"name": "DeltaBlue", "results": ["10657567"], "stddev": ""}, |
| 319 ]) | 319 ]) |
| 320 self._VerifyErrors( | 320 self._VerifyErrors( |
| 321 ["Regexp \"^Richards: (.+)$\" didn't match for benchmark Richards.", | 321 ["Regexp \"^Richards: (.+)$\" didn't match for test Richards.", |
| 322 "Not all traces have the same number of results."]) | 322 "Not all traces have the same number of results."]) |
| 323 self._VerifyMock(path.join("out", "Release", "d7"), "--flag", "run.js") | 323 self._VerifyMock(path.join("out", "Release", "d7"), "--flag", "run.js") |
| 324 | 324 |
| 325 def testRegexpNoMatch(self): | 325 def testRegexpNoMatch(self): |
| 326 self._WriteTestInput(V8_JSON) | 326 self._WriteTestInput(V8_JSON) |
| 327 self._MockCommand(["."], ["x\nRichaards: 1.234\nDeltaBlue: 10657567\ny\n"]) | 327 self._MockCommand(["."], ["x\nRichaards: 1.234\nDeltaBlue: 10657567\ny\n"]) |
| 328 self.assertEquals(1, self._CallMain()) | 328 self.assertEquals(1, self._CallMain()) |
| 329 self._VerifyResults("test", "score", [ | 329 self._VerifyResults("test", "score", [ |
| 330 {"name": "Richards", "results": [], "stddev": ""}, | 330 {"name": "Richards", "results": [], "stddev": ""}, |
| 331 {"name": "DeltaBlue", "results": ["10657567"], "stddev": ""}, | 331 {"name": "DeltaBlue", "results": ["10657567"], "stddev": ""}, |
| 332 ]) | 332 ]) |
| 333 self._VerifyErrors( | 333 self._VerifyErrors( |
| 334 ["Regexp \"^Richards: (.+)$\" didn't match for benchmark Richards."]) | 334 ["Regexp \"^Richards: (.+)$\" didn't match for test Richards."]) |
| 335 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js") | 335 self._VerifyMock(path.join("out", "x64.release", "d7"), "--flag", "run.js") |
| 336 | 336 |
| 337 def testOneRunGeneric(self): | 337 def testOneRunGeneric(self): |
| 338 test_input = dict(V8_GENERIC_JSON) | 338 test_input = dict(V8_GENERIC_JSON) |
| 339 self._WriteTestInput(test_input) | 339 self._WriteTestInput(test_input) |
| 340 self._MockCommand(["."], [ | 340 self._MockCommand(["."], [ |
| 341 "Trace(Test1), Result(1.234), StdDev(0.23)\n" | 341 "Trace(Test1), Result(1.234), StdDev(0.23)\n" |
| 342 "Trace(Test2), Result(10657567), StdDev(106)\n"]) | 342 "Trace(Test2), Result(10657567), StdDev(106)\n"]) |
| 343 self.assertEquals(0, self._CallMain()) | 343 self.assertEquals(0, self._CallMain()) |
| 344 self._VerifyResults("test", "ms", [ | 344 self._VerifyResults("test", "ms", [ |
| 345 {"name": "Test1", "results": ["1.234"], "stddev": "0.23"}, | 345 {"name": "Test1", "results": ["1.234"], "stddev": "0.23"}, |
| 346 {"name": "Test2", "results": ["10657567"], "stddev": "106"}, | 346 {"name": "Test2", "results": ["10657567"], "stddev": "106"}, |
| 347 ]) | 347 ]) |
| 348 self._VerifyErrors([]) | 348 self._VerifyErrors([]) |
| 349 self._VerifyMock(path.join("out", "x64.release", "cc"), "--flag", "") | 349 self._VerifyMock(path.join("out", "x64.release", "cc"), "--flag", "") |
| OLD | NEW |