Title: [137661] trunk/Tools
Revision
137661
Author
e...@webkit.org
Date
2012-12-13 15:17:17 -0800 (Thu, 13 Dec 2012)

Log Message

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):

Modified Paths

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)
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to