Diff
Modified: trunk/Tools/ChangeLog (137660 => 137661)
--- trunk/Tools/ChangeLog 2012-12-13 23:11:14 UTC (rev 137660)
+++ trunk/Tools/ChangeLog 2012-12-13 23:17:17 UTC (rev 137661)
@@ -1,3 +1,37 @@
+2012-12-13 Eric Seidel <e...@webkit.org>
+
+ Add --profiler=PROFILER option to run-perf-tests to allow specifying which profiler to use on platforms with many
+ https://bugs.webkit.org/show_bug.cgi?id=104891
+
+ Reviewed by Dirk Pranke.
+
+ I also implemented a very simple "Sample" Profiler using
+ Mac OS X's /usr/bin/sample command line tool.
+
+ I also moved the map(unicode, args) call into Executive.popen
+ so that all callers don't have to do it themselves.
+
+ The real reason for this abstraction is to make it easy
+ to support both perf and pprof on linux which seem to
+ be about equally popular among those I ask in the Chrome team.
+
+ * Scripts/webkitpy/common/system/executive.py:
+ (Executive.popen):
+ * Scripts/webkitpy/common/system/profiler.py:
+ (ProfilerFactory.create_profiler):
+ (ProfilerFactory):
+ (ProfilerFactory.available_profilers_by_name):
+ (ProfilerFactory.default_profiler_name):
+ (Sample):
+ (Sample.__init__):
+ (Sample.attach_to_pid):
+ (Sample.profile_after_exit):
+ (IProfiler.attach_to_pid):
+ * Scripts/webkitpy/layout_tests/port/driver.py:
+ (Driver.__init__):
+ * Scripts/webkitpy/performance_tests/perftestsrunner.py:
+ (PerfTestsRunner._parse_args):
+
2012-12-13 Dirk Pranke <dpra...@chromium.org>
support -wk2 port names properly in webkitpy.layout_tests.port
Modified: trunk/Tools/Scripts/webkitpy/common/system/executive.py (137660 => 137661)
--- trunk/Tools/Scripts/webkitpy/common/system/executive.py 2012-12-13 23:11:14 UTC (rev 137660)
+++ trunk/Tools/Scripts/webkitpy/common/system/executive.py 2012-12-13 23:17:17 UTC (rev 137661)
@@ -101,9 +101,6 @@
return sys.platform not in ('win32', 'cygwin')
def _run_command_with_teed_output(self, args, teed_output, **kwargs):
- args = map(unicode, args) # Popen will throw an exception if args are non-strings (like int())
- args = map(self._encode_argument_if_needed, args)
-
child_process = self.popen(args,
stdout=self.PIPE,
stderr=self.STDOUT,
@@ -390,8 +387,6 @@
"""Popen wrapper for convenience and to work around python bugs."""
assert(isinstance(args, list) or isinstance(args, tuple))
start_time = time.time()
- args = map(unicode, args) # Popen will throw an exception if args are non-strings (like int())
- args = map(self._encode_argument_if_needed, args)
stdin, string_to_communicate = self._compute_stdin(input)
stderr = self.STDOUT if return_stderr else None
@@ -458,7 +453,9 @@
return argument.encode(self._child_process_encoding())
def popen(self, *args, **kwargs):
- return subprocess.Popen(*args, **kwargs)
+ string_args = map(unicode, *args) # Popen will throw an exception if args are non-strings (like int())
+ string_args = map(self._encode_argument_if_needed, string_args)
+ return subprocess.Popen(string_args, **kwargs)
def run_in_parallel(self, command_lines_and_cwds, processes=None):
"""Runs a list of (cmd_line list, cwd string) tuples in parallel and returns a list of (retcode, stdout, stderr) tuples."""
Modified: trunk/Tools/Scripts/webkitpy/common/system/profiler.py (137660 => 137661)
--- trunk/Tools/Scripts/webkitpy/common/system/profiler.py 2012-12-13 23:11:14 UTC (rev 137660)
+++ trunk/Tools/Scripts/webkitpy/common/system/profiler.py 2012-12-13 23:17:17 UTC (rev 137661)
@@ -34,12 +34,30 @@
class ProfilerFactory(object):
@classmethod
- def create_profiler(cls, host, executable_path, output_dir, identifier=None):
- if host.platform.is_mac():
- return IProfiler(host, executable_path, output_dir, identifier)
- return GooglePProf(host, executable_path, output_dir, identifier)
+ def create_profiler(cls, host, executable_path, output_dir, profiler_name=None, identifier=None):
+ profilers_by_name = cls.available_profilers_by_name(host.platform)
+ profiler_class = profilers_by_name.get(profiler_name or cls.default_profiler_name(host.platform))
+ if not profiler_class:
+ return None
+ return profiler_class(host, executable_path, output_dir, identifier)
+ @classmethod
+ def available_profilers_by_name(cls, platform):
+ profilers = {'pprof': GooglePProf}
+ if platform.is_mac():
+ profilers['iprofiler'] = IProfiler
+ profilers['sample'] = Sample
+ return profilers
+ @classmethod
+ def default_profiler_name(cls, platform):
+ if platform.is_mac():
+ return 'iprofiler'
+ if platform.is_linux():
+ return 'pprof'
+ return None
+
+
class Profiler(object):
def __init__(self, host, executable_path, output_dir, identifier=None):
self._host = host
@@ -91,6 +109,20 @@
print self._first_ten_lines_of_profile(profile_text)
+class Sample(SingleFileOutputProfiler):
+ def __init__(self, host, executable_path, output_dir, identifier=None):
+ super(Sample, self).__init__(host, executable_path, output_dir, "txt", identifier)
+ self._profiler_process = None
+
+ def attach_to_pid(self, pid):
+ fs = self._host.filesystem
+ cmd = ["sample", pid, "-mayDie", "-file", self._output_path]
+ self._profiler_process = self._host.executive.popen(cmd)
+
+ def profile_after_exit(self):
+ self._profiler_process.wait()
+
+
class IProfiler(SingleFileOutputProfiler):
def __init__(self, host, executable_path, output_dir, identifier=None):
super(IProfiler, self).__init__(host, executable_path, output_dir, "dtps", identifier)
@@ -102,7 +134,6 @@
fs = self._host.filesystem
cmd = ["iprofiler", "-timeprofiler", "-a", pid,
"-d", fs.dirname(self._output_path), "-o", fs.splitext(fs.basename(self._output_path))[0]]
- cmd = map(unicode, cmd)
# FIXME: Consider capturing instead of letting instruments spam to stderr directly.
self._profiler_process = self._host.executive.popen(cmd)
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/driver.py (137660 => 137661)
--- trunk/Tools/Scripts/webkitpy/layout_tests/port/driver.py 2012-12-13 23:11:14 UTC (rev 137660)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/driver.py 2012-12-13 23:17:17 UTC (rev 137661)
@@ -143,7 +143,9 @@
self._measurements = {}
if self._port.get_option("profile"):
- self._profiler = ProfilerFactory.create_profiler(self._port.host, self._port._path_to_driver(), self._port.results_directory())
+ profiler_name = self._port.get_option("profiler")
+ self._profiler = ProfilerFactory.create_profiler(self._port.host,
+ self._port._path_to_driver(), self._port.results_directory(), profiler_name)
else:
self._profiler = None
Modified: trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py (137660 => 137661)
--- trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py 2012-12-13 23:11:14 UTC (rev 137660)
+++ trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py 2012-12-13 23:17:17 UTC (rev 137661)
@@ -122,6 +122,8 @@
help="Run all tests, including the ones in the Skipped list."),
optparse.make_option("--profile", action=""
help="Output per-test profile information."),
+ optparse.make_option("--profiler", action=""
+ help="Output per-test profile information, using the specified profiler."),
]
return optparse.OptionParser(option_list=(perf_option_list)).parse_args(args)