Chromium Code Reviews| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 The test flags are passed to the js test file after '--'. | 95 The test flags are passed to the js test file after '--'. |
| 96 """ | 96 """ |
| 97 | 97 |
| 98 from collections import OrderedDict | 98 from collections import OrderedDict |
| 99 import json | 99 import json |
| 100 import logging | 100 import logging |
| 101 import math | 101 import math |
| 102 import optparse | 102 import optparse |
| 103 import os | 103 import os |
| 104 import re | 104 import re |
| 105 import subprocess | |
| 105 import sys | 106 import sys |
| 106 | 107 |
| 107 from testrunner.local import commands | 108 from testrunner.local import commands |
| 108 from testrunner.local import utils | 109 from testrunner.local import utils |
| 109 | 110 |
| 110 ARCH_GUESS = utils.DefaultArch() | 111 ARCH_GUESS = utils.DefaultArch() |
| 111 SUPPORTED_ARCHS = ["arm", | 112 SUPPORTED_ARCHS = ["arm", |
| 112 "ia32", | 113 "ia32", |
| 113 "mips", | 114 "mips", |
| 114 "mipsel", | 115 "mipsel", |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 448 The tests are supposed to be relative to the suite configuration. | 449 The tests are supposed to be relative to the suite configuration. |
| 449 """ | 450 """ |
| 450 suite_dir = os.path.abspath(os.path.dirname(suite_path)) | 451 suite_dir = os.path.abspath(os.path.dirname(suite_path)) |
| 451 bench_dir = os.path.normpath(os.path.join(*self.path)) | 452 bench_dir = os.path.normpath(os.path.join(*self.path)) |
| 452 os.chdir(os.path.join(suite_dir, bench_dir)) | 453 os.chdir(os.path.join(suite_dir, bench_dir)) |
| 453 | 454 |
| 454 def GetCommandFlags(self, extra_flags=None): | 455 def GetCommandFlags(self, extra_flags=None): |
| 455 suffix = ["--"] + self.test_flags if self.test_flags else [] | 456 suffix = ["--"] + self.test_flags if self.test_flags else [] |
| 456 return self.flags + (extra_flags or []) + [self.main] + suffix | 457 return self.flags + (extra_flags or []) + [self.main] + suffix |
| 457 | 458 |
| 458 def GetCommand(self, shell_dir, extra_flags=None): | 459 def GetCommand(self, shell_dir, extra_flags=None, profiler_run=False): |
| 459 # TODO(machenbach): This requires +.exe if run on windows. | 460 # TODO(machenbach): This requires +.exe if run on windows. |
| 460 cmd = [os.path.join(shell_dir, self.binary)] | 461 cmd = [os.path.join(shell_dir, self.binary)] |
| 462 if self.binary == 'd8' and profiler_run: | |
| 463 cmd = cmd + ["--prof"] | |
| 464 else: | |
| 465 print "Profiler supported only on a benchmark run with d8" | |
| 461 return cmd + self.GetCommandFlags(extra_flags=extra_flags) | 466 return cmd + self.GetCommandFlags(extra_flags=extra_flags) |
| 462 | 467 |
| 463 def Run(self, runner, trybot): | 468 def Run(self, runner, trybot): |
| 464 """Iterates over several runs and handles the output for all traces.""" | 469 """Iterates over several runs and handles the output for all traces.""" |
| 465 stdout_with_patch, stdout_no_patch = Unzip(runner()) | 470 stdout_with_patch, stdout_no_patch = Unzip(runner()) |
| 466 return ( | 471 return ( |
| 467 AccumulateResults( | 472 AccumulateResults( |
| 468 self.graphs, | 473 self.graphs, |
| 469 self._children, | 474 self._children, |
| 470 iter_output=stdout_with_patch, | 475 iter_output=stdout_with_patch, |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 self.shell_dir_no_patch = options.shell_dir_no_patch | 581 self.shell_dir_no_patch = options.shell_dir_no_patch |
| 577 self.extra_flags = options.extra_flags.split() | 582 self.extra_flags = options.extra_flags.split() |
| 578 | 583 |
| 579 @staticmethod | 584 @staticmethod |
| 580 def GetPlatform(options): | 585 def GetPlatform(options): |
| 581 if options.android_build_tools: | 586 if options.android_build_tools: |
| 582 return AndroidPlatform(options) | 587 return AndroidPlatform(options) |
| 583 else: | 588 else: |
| 584 return DesktopPlatform(options) | 589 return DesktopPlatform(options) |
| 585 | 590 |
| 586 def _Run(self, runnable, count, no_patch=False): | 591 def _Run(self, runnable, count, no_patch=False, profiler_run=False): |
| 587 raise NotImplementedError() # pragma: no cover | 592 raise NotImplementedError() # pragma: no cover |
| 588 | 593 |
| 589 def Run(self, runnable, count): | 594 def Run(self, runnable, count, profiler_run=False): |
| 590 """Execute the benchmark's main file. | 595 """Execute the benchmark's main file. |
| 591 | 596 |
| 592 If options.shell_dir_no_patch is specified, the benchmark is run once with | 597 If options.shell_dir_no_patch is specified, the benchmark is run once with |
| 593 and once without patch. | 598 and once without patch. |
| 594 Args: | 599 Args: |
| 595 runnable: A Runnable benchmark instance. | 600 runnable: A Runnable benchmark instance. |
| 596 count: The number of this (repeated) run. | 601 count: The number of this (repeated) run. |
| 597 Returns: A tuple with the benchmark outputs with and without patch. The | 602 Returns: A tuple with the benchmark outputs with and without patch. The |
| 598 latter will be None if options.shell_dir_no_patch was not | 603 latter will be None if options.shell_dir_no_patch was not |
| 599 specified. | 604 specified. |
| 600 """ | 605 """ |
| 601 stdout = self._Run(runnable, count, no_patch=False) | 606 stdout = self._Run(runnable, count, no_patch=False, |
| 607 profiler_run=profiler_run) | |
| 602 if self.shell_dir_no_patch: | 608 if self.shell_dir_no_patch: |
| 603 return stdout, self._Run(runnable, count, no_patch=True) | 609 return stdout, self._Run(runnable, count, no_patch=True, |
| 610 profiler_run=profiler_run) | |
| 604 else: | 611 else: |
| 605 return stdout, None | 612 return stdout, None |
| 606 | 613 |
| 607 | 614 |
| 608 class DesktopPlatform(Platform): | 615 class DesktopPlatform(Platform): |
| 609 def __init__(self, options): | 616 def __init__(self, options): |
| 610 super(DesktopPlatform, self).__init__(options) | 617 super(DesktopPlatform, self).__init__(options) |
| 611 | 618 |
| 612 def PreExecution(self): | 619 def PreExecution(self): |
| 613 pass | 620 pass |
| 614 | 621 |
| 615 def PostExecution(self): | 622 def PostExecution(self): |
| 616 pass | 623 pass |
| 617 | 624 |
| 618 def PreTests(self, node, path): | 625 def PreTests(self, node, path): |
| 619 if isinstance(node, RunnableConfig): | 626 if isinstance(node, RunnableConfig): |
| 620 node.ChangeCWD(path) | 627 node.ChangeCWD(path) |
| 621 | 628 |
| 622 def _Run(self, runnable, count, no_patch=False): | 629 def _Run(self, runnable, count, no_patch=False, profiler_run=False): |
| 623 suffix = ' - without patch' if no_patch else '' | 630 suffix = ' - without patch' if no_patch else '' |
| 624 shell_dir = self.shell_dir_no_patch if no_patch else self.shell_dir | 631 shell_dir = self.shell_dir_no_patch if no_patch else self.shell_dir |
| 625 title = ">>> %%s (#%d)%s:" % ((count + 1), suffix) | 632 title = ">>> %%s (#%d)%s:" % ((count + 1), suffix) |
| 626 try: | 633 try: |
| 627 output = commands.Execute( | 634 output = commands.Execute( |
| 628 runnable.GetCommand(shell_dir, self.extra_flags), | 635 runnable.GetCommand(shell_dir, self.extra_flags, |
| 636 profiler_run=profiler_run), | |
| 629 timeout=runnable.timeout, | 637 timeout=runnable.timeout, |
| 630 ) | 638 ) |
| 631 except OSError as e: # pragma: no cover | 639 except OSError as e: # pragma: no cover |
| 632 print title % "OSError" | 640 print title % "OSError" |
| 633 print e | 641 print e |
| 634 return "" | 642 return "" |
| 635 print title % "Stdout" | 643 print title % "Stdout" |
| 636 print output.stdout | 644 print output.stdout |
| 637 if output.stderr: # pragma: no cover | 645 if output.stderr: # pragma: no cover |
| 638 # Print stderr for debugging. | 646 # Print stderr for debugging. |
| 639 print title % "Stderr" | 647 print title % "Stderr" |
| 640 print output.stderr | 648 print output.stderr |
| 641 if output.timed_out: | 649 if output.timed_out: |
| 642 print ">>> Test timed out after %ss." % runnable.timeout | 650 print ">>> Test timed out after %ss." % runnable.timeout |
| 651 if profiler_run: | |
|
Michael Achenbach
2015/09/10 07:49:44
Suggestion: Could you maybe just use the existing
gdeepti1
2015/09/11 08:22:33
Currently passing in the --profiler flag to run_pe
Michael Achenbach
2015/09/11 09:13:02
Hmm - not sure if I understand. I don't wanna impl
gdeepti1
2015/09/11 20:05:57
Thanks for clarifying, simplified to use --extra-f
| |
| 652 if utils.GuessOS() == "linux": | |
| 653 tick_tools = os.path.abspath(os.path.join(shell_dir, "..", "..", | |
| 654 "tools", | |
| 655 "linux-tick-processor")) | |
| 656 elif utils.GuessOS() == "macos": | |
| 657 tick_tools = os.path.abspath(os.path.join(shell_dir, "..", "..", | |
| 658 "tools", | |
| 659 "mac-tick-processor")) | |
| 660 else: | |
| 661 print "Profiler option currently supported on Linux and Mac OS." | |
| 662 prof_cmd = tick_tools + " --only-summary" | |
| 663 subprocess.check_call(prof_cmd, shell=True) | |
| 643 return output.stdout | 664 return output.stdout |
| 644 | 665 |
| 645 | 666 |
| 646 class AndroidPlatform(Platform): # pragma: no cover | 667 class AndroidPlatform(Platform): # pragma: no cover |
| 647 DEVICE_DIR = "/data/local/tmp/v8/" | 668 DEVICE_DIR = "/data/local/tmp/v8/" |
| 648 | 669 |
| 649 def __init__(self, options): | 670 def __init__(self, options): |
| 650 super(AndroidPlatform, self).__init__(options) | 671 super(AndroidPlatform, self).__init__(options) |
| 651 LoadAndroidBuildTools(options.android_build_tools) | 672 LoadAndroidBuildTools(options.android_build_tools) |
| 652 | 673 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 793 help="Additional flags to pass to the test executable", | 814 help="Additional flags to pass to the test executable", |
| 794 default="") | 815 default="") |
| 795 parser.add_option("--json-test-results", | 816 parser.add_option("--json-test-results", |
| 796 help="Path to a file for storing json results.") | 817 help="Path to a file for storing json results.") |
| 797 parser.add_option("--json-test-results-no-patch", | 818 parser.add_option("--json-test-results-no-patch", |
| 798 help="Path to a file for storing json results from run " | 819 help="Path to a file for storing json results from run " |
| 799 "without patch.") | 820 "without patch.") |
| 800 parser.add_option("--outdir", help="Base directory with compile output", | 821 parser.add_option("--outdir", help="Base directory with compile output", |
| 801 default="out") | 822 default="out") |
| 802 parser.add_option("--outdir-no-patch", | 823 parser.add_option("--outdir-no-patch", |
| 803 help="Base directory with compile output without patch") | 824 help="Base directory with compile output without patch"), |
| 825 parser.add_option("--profiler", | |
| 826 help="Run with the profiler and print the summary " | |
| 827 "for each run", | |
| 828 default=False, action="store_true") | |
| 804 (options, args) = parser.parse_args(args) | 829 (options, args) = parser.parse_args(args) |
| 805 | 830 |
| 806 if len(args) == 0: # pragma: no cover | 831 if len(args) == 0: # pragma: no cover |
| 807 parser.print_help() | 832 parser.print_help() |
| 808 return 1 | 833 return 1 |
| 809 | 834 |
| 810 if options.arch in ["auto", "native"]: # pragma: no cover | 835 if options.arch in ["auto", "native"]: # pragma: no cover |
| 811 options.arch = ARCH_GUESS | 836 options.arch = ARCH_GUESS |
| 812 | 837 |
| 813 if not options.arch in SUPPORTED_ARCHS: # pragma: no cover | 838 if not options.arch in SUPPORTED_ARCHS: # pragma: no cover |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 868 | 893 |
| 869 # Traverse graph/trace tree and interate over all runnables. | 894 # Traverse graph/trace tree and interate over all runnables. |
| 870 for runnable in FlattenRunnables(root, NodeCB): | 895 for runnable in FlattenRunnables(root, NodeCB): |
| 871 print ">>> Running suite: %s" % "/".join(runnable.graphs) | 896 print ">>> Running suite: %s" % "/".join(runnable.graphs) |
| 872 | 897 |
| 873 def Runner(): | 898 def Runner(): |
| 874 """Output generator that reruns several times.""" | 899 """Output generator that reruns several times.""" |
| 875 for i in xrange(0, max(1, runnable.run_count)): | 900 for i in xrange(0, max(1, runnable.run_count)): |
| 876 # TODO(machenbach): Allow timeout per arch like with run_count per | 901 # TODO(machenbach): Allow timeout per arch like with run_count per |
| 877 # arch. | 902 # arch. |
| 878 yield platform.Run(runnable, i) | 903 yield platform.Run(runnable, i, options.profiler) |
| 879 | 904 |
| 880 # Let runnable iterate over all runs and handle output. | 905 # Let runnable iterate over all runs and handle output. |
| 881 result, result_no_patch = runnable.Run( | 906 result, result_no_patch = runnable.Run( |
| 882 Runner, trybot=options.shell_dir_no_patch) | 907 Runner, trybot=options.shell_dir_no_patch) |
| 883 results += result | 908 results += result |
| 884 results_no_patch += result_no_patch | 909 results_no_patch += result_no_patch |
| 885 platform.PostExecution() | 910 platform.PostExecution() |
| 886 | 911 |
| 887 if options.json_test_results: | 912 if options.json_test_results: |
| 888 results.WriteToFile(options.json_test_results) | 913 results.WriteToFile(options.json_test_results) |
| 889 else: # pragma: no cover | 914 else: # pragma: no cover |
| 890 print results | 915 print results |
| 891 | 916 |
| 892 if options.json_test_results_no_patch: | 917 if options.json_test_results_no_patch: |
| 893 results_no_patch.WriteToFile(options.json_test_results_no_patch) | 918 results_no_patch.WriteToFile(options.json_test_results_no_patch) |
| 894 else: # pragma: no cover | 919 else: # pragma: no cover |
| 895 print results_no_patch | 920 print results_no_patch |
| 896 | 921 |
| 897 return min(1, len(results.errors)) | 922 return min(1, len(results.errors)) |
| 898 | 923 |
| 899 if __name__ == "__main__": # pragma: no cover | 924 if __name__ == "__main__": # pragma: no cover |
| 900 sys.exit(Main(sys.argv[1:])) | 925 sys.exit(Main(sys.argv[1:])) |
| OLD | NEW |