Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(540)

Side by Side Diff: tools/run_perf.py

Issue 1915303002: [tools] Specify affinity and raise priority when benchmarking (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 594 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 stdout = self._Run(runnable, count, no_patch=False) 605 stdout = self._Run(runnable, count, no_patch=False)
606 if self.shell_dir_no_patch: 606 if self.shell_dir_no_patch:
607 return stdout, self._Run(runnable, count, no_patch=True) 607 return stdout, self._Run(runnable, count, no_patch=True)
608 else: 608 else:
609 return stdout, None 609 return stdout, None
610 610
611 611
612 class DesktopPlatform(Platform): 612 class DesktopPlatform(Platform):
613 def __init__(self, options): 613 def __init__(self, options):
614 super(DesktopPlatform, self).__init__(options) 614 super(DesktopPlatform, self).__init__(options)
615 self.command_prefix = []
616
617 if options.prioritize or options.affinitize != None:
618 self.command_prefix = ["schedtool"]
619 if options.prioritize:
620 self.command_prefix += ["-n", "-20"]
621 if options.affinitize != None:
622 # schedtool expects a bit pattern when setting affinity, where each
623 # bit set to '1' corresponds to a core where the process may run on.
624 # First bit corresponds to CPU 0. Since the 'affinitize' parameter is
625 # a core number, we need to map to said bit pattern.
626 cpu = int(options.affinitize)
627 core = 1 << cpu
628 self.command_prefix += ["-a", ("0x%x" % core)]
Michael Achenbach 2016/04/28 13:03:07 Another question to this: Now we set exactly one c
Mircea Trofin 2016/04/28 14:21:57 Multi-core may introduce other sources of variance
629 self.command_prefix += ["-e"]
615 630
616 def PreExecution(self): 631 def PreExecution(self):
617 pass 632 pass
618 633
619 def PostExecution(self): 634 def PostExecution(self):
620 pass 635 pass
621 636
622 def PreTests(self, node, path): 637 def PreTests(self, node, path):
623 if isinstance(node, RunnableConfig): 638 if isinstance(node, RunnableConfig):
624 node.ChangeCWD(path) 639 node.ChangeCWD(path)
625 640
626 def _Run(self, runnable, count, no_patch=False): 641 def _Run(self, runnable, count, no_patch=False):
627 suffix = ' - without patch' if no_patch else '' 642 suffix = ' - without patch' if no_patch else ''
628 shell_dir = self.shell_dir_no_patch if no_patch else self.shell_dir 643 shell_dir = self.shell_dir_no_patch if no_patch else self.shell_dir
629 title = ">>> %%s (#%d)%s:" % ((count + 1), suffix) 644 title = ">>> %%s (#%d)%s:" % ((count + 1), suffix)
645 command = self.command_prefix + runnable.GetCommand(shell_dir,
646 self.extra_flags)
630 try: 647 try:
631 output = commands.Execute( 648 output = commands.Execute(
632 runnable.GetCommand(shell_dir, self.extra_flags), 649 command,
633 timeout=runnable.timeout, 650 timeout=runnable.timeout,
634 ) 651 )
635 except OSError as e: # pragma: no cover 652 except OSError as e: # pragma: no cover
636 print title % "OSError" 653 print title % "OSError"
637 print e 654 print e
638 return "" 655 return ""
656
639 print title % "Stdout" 657 print title % "Stdout"
640 print output.stdout 658 print output.stdout
641 if output.stderr: # pragma: no cover 659 if output.stderr: # pragma: no cover
642 # Print stderr for debugging. 660 # Print stderr for debugging.
643 print title % "Stderr" 661 print title % "Stderr"
644 print output.stderr 662 print output.stderr
645 if output.timed_out: 663 if output.timed_out:
646 print ">>> Test timed out after %ss." % runnable.timeout 664 print ">>> Test timed out after %ss." % runnable.timeout
647 if '--prof' in self.extra_flags: 665 if '--prof' in self.extra_flags:
648 os_prefix = {"linux": "linux", "macos": "mac"}.get(utils.GuessOS()) 666 os_prefix = {"linux": "linux", "macos": "mac"}.get(utils.GuessOS())
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 ) 800 )
783 stdout = "\n".join(output) 801 stdout = "\n".join(output)
784 print title % "Stdout" 802 print title % "Stdout"
785 print stdout 803 print stdout
786 except device_errors.CommandTimeoutError: 804 except device_errors.CommandTimeoutError:
787 print ">>> Test timed out after %ss." % runnable.timeout 805 print ">>> Test timed out after %ss." % runnable.timeout
788 stdout = "" 806 stdout = ""
789 return stdout 807 return stdout
790 808
791 809
810 def GetASLR():
811 try:
812 f = os.open("/proc/sys/kernel/randomize_va_space", os.O_RDONLY)
Michael Achenbach 2016/04/28 14:47:44 Could you use with clauses? Also below. with open(
Mircea Trofin 2016/04/28 16:02:46 Done.
813 val = os.read(f, 1)
814 os.close(f)
815 return int(val)
816 except Exception as e:
817 print "Failed to get current ASLR settings."
818 raise e
819
820 def SetASLR(value):
821 try:
822 f = os.open("/proc/sys/kernel/randomize_va_space", os.O_WRONLY)
823 val = os.write(f, str(value))
824 os.close(f)
825
826 new_value = GetASLR()
827 if value != new_value: raise Exception("Present value is %s" % new_value)
Michael Achenbach 2016/04/28 14:47:44 Maybe move this condition outside the try block to
Mircea Trofin 2016/04/28 16:02:46 Done.
828 except Exception as e:
829 print "Failed to update ASLR to %s." % value
830 raise e
831
832 def GetCPUCoresRange():
833 try:
834 f = open("/sys/devices/system/cpu/present", "r")
835 indexes = f.readline()
836 [first, last] = map(int, indexes.split("-"))
Michael Achenbach 2016/04/28 14:47:44 first, last = map(int, indexes.split("-")) should
Mircea Trofin 2016/04/28 16:02:47 Done.
837 return range(first, last + 1)
838 except Exception as e:
839 print "Failed to retrieve CPU governor value"
840 raise e
841
842 def GetCPUPathForId(cpu_index):
843 ret = "/sys/devices/system/cpu/cpu"
844 ret += str(cpu_index)
845 ret += "/cpufreq/scaling_governor"
846 return ret
847
848 def GetCPUGovernor():
849 try:
850 cpu_indices = GetCPUCoresRange()
851 ret = None
852 for cpu_index in cpu_indices:
Michael Achenbach 2016/04/28 14:47:44 nit: Maybe inline GetCPUCoresRange() also in metho
Mircea Trofin 2016/04/28 16:02:46 I didn't understand what you meant here.
Michael Achenbach 2016/04/29 07:40:32 I meant to skip the local variable. But now that t
853 f = open(GetCPUPathForId(cpu_index), "r")
854 # We assume the governors of all CPUs are set to the same value
855 val = f.readline().strip()
856 f.close()
857 if ret == None:
858 ret = val
859 else:
Michael Achenbach 2016/04/28 14:47:44 elif ret != val:
Mircea Trofin 2016/04/28 16:02:46 Done.
860 if ret != val:
861 raise Exception("CPU cores have differing governor settings")
862 return ret
863 except Exception as e:
864 print "Failed to get the current CPU governor."
865 raise e
866
867
868 def SetCPUGovernor(value):
869 try:
870 cpu_indices = GetCPUCoresRange()
871 for cpu_index in cpu_indices:
872 f = open(GetCPUPathForId(cpu_index), "w")
873 f.write(value)
874 f.close()
875
876 cur_value = GetCPUGovernor()
877 if cur_value != value:
Michael Achenbach 2016/04/28 14:47:44 same as above - move condition outside try
Mircea Trofin 2016/04/28 16:02:46 Done.
878 raise Exception("Could not set CPU governor. Present value is %s"
879 % cur_value )
880 except Exception as e:
881 print "Failed to change CPU governor to %s." % value
882 raise e
883
792 # TODO: Implement results_processor. 884 # TODO: Implement results_processor.
793 def Main(args): 885 def Main(args):
794 logging.getLogger().setLevel(logging.INFO) 886 logging.getLogger().setLevel(logging.INFO)
795 parser = optparse.OptionParser() 887 parser = optparse.OptionParser()
796 parser.add_option("--android-build-tools", 888 parser.add_option("--android-build-tools",
797 help="Path to chromium's build/android. Specifying this " 889 help="Path to chromium's build/android. Specifying this "
798 "option will run tests using android platform.") 890 "option will run tests using android platform.")
799 parser.add_option("--arch", 891 parser.add_option("--arch",
800 help=("The architecture to run tests for, " 892 help=("The architecture to run tests for, "
801 "'auto' or 'native' for auto-detect"), 893 "'auto' or 'native' for auto-detect"),
(...skipping 13 matching lines...) Expand all
815 help="Path to a file for storing json results from run " 907 help="Path to a file for storing json results from run "
816 "without patch.") 908 "without patch.")
817 parser.add_option("--outdir", help="Base directory with compile output", 909 parser.add_option("--outdir", help="Base directory with compile output",
818 default="out") 910 default="out")
819 parser.add_option("--outdir-no-patch", 911 parser.add_option("--outdir-no-patch",
820 help="Base directory with compile output without patch") 912 help="Base directory with compile output without patch")
821 parser.add_option("--binary-override-path", 913 parser.add_option("--binary-override-path",
822 help="JavaScript engine binary. By default, d8 under " 914 help="JavaScript engine binary. By default, d8 under "
823 "architecture-specific build dir. " 915 "architecture-specific build dir. "
824 "Not supported in conjunction with outdir-no-patch.") 916 "Not supported in conjunction with outdir-no-patch.")
917 parser.add_option("--prioritize",
918 help="Raise the priority to nice -20 for the benchmarking"
919 "process.Requires Linux, schedtool, and sudo privileges.",
920 default=False, action="store_true")
921 parser.add_option("--affinitize",
922 help="Run benchmarking process on the specified core."
923 "For example:"
924 "--affinitize=0 will run the benchmark process on core 0."
925 "--affinitize=3 will run the benchmark process on core 3."
926 "Requires Linux, schedtool, and sudo privileges.",
927 default=None)
928 parser.add_option("--noaslr",
929 help="Disable ASLR for the duration of the benchmarked"
930 "process. Requires Linux and sudo privileges.",
931 default=False, action="store_true")
932 parser.add_option("--cpu-governor",
933 help="Set cpu governor to specified policy for the"
Michael Achenbach 2016/04/28 14:47:43 nit: Space before " to not concatenate strings.
Mircea Trofin 2016/04/28 16:02:46 Done.
934 "duration of the benchmarked process. Typical options:"
935 "'powersave' for more stable results, or 'performance'"
936 "for shorter completion time of suite, with potentially"
937 "more noise in results.")
825 938
826 (options, args) = parser.parse_args(args) 939 (options, args) = parser.parse_args(args)
827 940
828 if len(args) == 0: # pragma: no cover 941 if len(args) == 0: # pragma: no cover
829 parser.print_help() 942 parser.print_help()
830 return 1 943 return 1
831 944
832 if options.arch in ["auto", "native"]: # pragma: no cover 945 if options.arch in ["auto", "native"]: # pragma: no cover
833 options.arch = ARCH_GUESS 946 options.arch = ARCH_GUESS
834 947
(...skipping 30 matching lines...) Expand all
865 return 1 978 return 1
866 options.shell_dir = os.path.dirname(options.binary_override_path) 979 options.shell_dir = os.path.dirname(options.binary_override_path)
867 default_binary_name = os.path.basename(options.binary_override_path) 980 default_binary_name = os.path.basename(options.binary_override_path)
868 981
869 if options.outdir_no_patch: 982 if options.outdir_no_patch:
870 options.shell_dir_no_patch = os.path.join( 983 options.shell_dir_no_patch = os.path.join(
871 workspace, options.outdir_no_patch, build_config) 984 workspace, options.outdir_no_patch, build_config)
872 else: 985 else:
873 options.shell_dir_no_patch = None 986 options.shell_dir_no_patch = None
874 987
988 prev_aslr = None
989 prev_cpu_gov = None
990 if options.noaslr:
991 prev_aslr = GetASLR()
992 SetASLR(0)
993 if options.cpu_governor:
994 prev_cpu_gov = GetCPUGovernor()
995 SetCPUGovernor(options.cpu_governor)
996
875 platform = Platform.GetPlatform(options) 997 platform = Platform.GetPlatform(options)
876 998
877 results = Results() 999 results = Results()
878 results_no_patch = Results() 1000 results_no_patch = Results()
879 for path in args: 1001 for path in args:
880 path = os.path.abspath(path) 1002 path = os.path.abspath(path)
881 1003
882 if not os.path.exists(path): # pragma: no cover 1004 if not os.path.exists(path): # pragma: no cover
883 results.errors.append("Configuration file %s does not exist." % path) 1005 results.errors.append("Configuration file %s does not exist." % path)
884 continue 1006 continue
(...skipping 25 matching lines...) Expand all
910 # TODO(machenbach): Allow timeout per arch like with run_count per 1032 # TODO(machenbach): Allow timeout per arch like with run_count per
911 # arch. 1033 # arch.
912 yield platform.Run(runnable, i) 1034 yield platform.Run(runnable, i)
913 1035
914 # Let runnable iterate over all runs and handle output. 1036 # Let runnable iterate over all runs and handle output.
915 result, result_no_patch = runnable.Run( 1037 result, result_no_patch = runnable.Run(
916 Runner, trybot=options.shell_dir_no_patch) 1038 Runner, trybot=options.shell_dir_no_patch)
917 results += result 1039 results += result
918 results_no_patch += result_no_patch 1040 results_no_patch += result_no_patch
919 platform.PostExecution() 1041 platform.PostExecution()
920 1042
Michael Achenbach 2016/04/28 14:47:44 Please refactor and put everything between setting
Mircea Trofin 2016/04/28 16:02:47 Thanks for the suggestion - this makes sense. I mo
Michael Achenbach 2016/04/29 07:40:32 Very nice!
1043 if prev_aslr != None:
1044 SetASLR(prev_aslr)
1045 if prev_cpu_gov != None:
1046 SetCPUGovernor(prev_cpu_gov)
1047
921 if options.json_test_results: 1048 if options.json_test_results:
922 results.WriteToFile(options.json_test_results) 1049 results.WriteToFile(options.json_test_results)
923 else: # pragma: no cover 1050 else: # pragma: no cover
924 print results 1051 print results
925 1052
926 if options.json_test_results_no_patch: 1053 if options.json_test_results_no_patch:
927 results_no_patch.WriteToFile(options.json_test_results_no_patch) 1054 results_no_patch.WriteToFile(options.json_test_results_no_patch)
928 else: # pragma: no cover 1055 else: # pragma: no cover
929 print results_no_patch 1056 print results_no_patch
930 1057
931 return min(1, len(results.errors)) 1058 return min(1, len(results.errors))
932 1059
933 if __name__ == "__main__": # pragma: no cover 1060 if __name__ == "__main__": # pragma: no cover
934 sys.exit(Main(sys.argv[1:])) 1061 sys.exit(Main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698