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 |