Nir Soffer has uploaded a new change for review.

Change subject: profile: Support yappi builtins option
......................................................................

profile: Support yappi builtins option

yappi support profiling also builtin python functions. This patch adds a
new configuration value to enable profiling builtins in an application
wide profile, and a new builtins kwarg to the profile decorator.

This option can be handy when trying to understand why code is
expensive.

Change-Id: I67c6fc52ac64f8ff7f13471a53129a66361192ca
Signed-off-by: Nir Soffer <[email protected]>
---
M lib/vdsm/config.py.in
M lib/vdsm/profile.py
M tests/profileTests.py
3 files changed, 66 insertions(+), 5 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/87/27787/1

diff --git a/lib/vdsm/config.py.in b/lib/vdsm/config.py.in
index 0656404..01d5580 100644
--- a/lib/vdsm/config.py.in
+++ b/lib/vdsm/config.py.in
@@ -35,6 +35,10 @@
         ('profile_format', 'pstat',
             'Profile file format (pstat, callgrind, ystat)'),
 
+        ('profile_builtins', 'false',
+            'Profile builtin functions used by standart Python modules. '
+            'false by default.'),
+
         ('host_mem_reserve', '256',
             'Reserves memory for the host to prevent VMs from using all the '
             'physical pages. The values are in Mbytes.'),
diff --git a/lib/vdsm/profile.py b/lib/vdsm/profile.py
index dbdf81a..809e1dc 100644
--- a/lib/vdsm/profile.py
+++ b/lib/vdsm/profile.py
@@ -35,6 +35,7 @@
 
 _FILENAME = os.path.join(constants.P_VDSM_RUN, 'vdsmd.prof')
 _FORMAT = config.get('vars', 'profile_format')
+_BUILTINS = config.getboolean('vars', 'profile_builtins')
 
 _lock = threading.Lock()
 
@@ -46,7 +47,7 @@
 def start():
     """ Starts application wide profiling """
     if is_enabled():
-        _start_profiling()
+        _start_profiling(builtins=_BUILTINS)
 
 
 def stop():
@@ -64,7 +65,7 @@
         return yappi and yappi.is_running()
 
 
-def profile(filename, format=_FORMAT):
+def profile(filename, format=_FORMAT, builtins=False):
     """
     Profile decorated function, saving profile to filename using format.
 
@@ -74,7 +75,7 @@
     def decorator(f):
         @wraps(f)
         def wrapper(*a, **kw):
-            _start_profiling()
+            _start_profiling(builtins=builtins)
             try:
                 return f(*a, **kw)
             finally:
@@ -83,7 +84,7 @@
     return decorator
 
 
-def _start_profiling():
+def _start_profiling(builtins=False):
     global yappi
     logging.debug("Starting profiling")
     with _lock:
@@ -93,7 +94,7 @@
         # that thinks they own the single process profiler.
         if yappi.is_running():
             raise Error('Profiler is already running')
-        yappi.start()
+        yappi.start(builtins=builtins)
 
 
 def _stop_profiling(filename, format):
diff --git a/tests/profileTests.py b/tests/profileTests.py
index d1760f7..cf9abbf 100644
--- a/tests/profileTests.py
+++ b/tests/profileTests.py
@@ -19,6 +19,7 @@
 #
 
 import ConfigParser
+import StringIO
 import errno
 import os
 import pstats
@@ -86,6 +87,30 @@
 
     @MonkeyPatch(profile, 'config', make_config(enable='true'))
     @MonkeyPatch(profile, '_FILENAME', FILENAME)
+    @MonkeyPatch(profile, '_FORMAT', 'pstat')
+    @MonkeyPatch(profile, '_BUILTINS', True)
+    def test_with_builtins(self):
+        requires_yappi()
+        profile.start()
+        dict()
+        profile.stop()
+        out = read_pstats(FILENAME)
+        self.assertIn('__builtin__:0', out)
+
+    @MonkeyPatch(profile, 'config', make_config(enable='true'))
+    @MonkeyPatch(profile, '_FILENAME', FILENAME)
+    @MonkeyPatch(profile, '_FORMAT', 'pstat')
+    @MonkeyPatch(profile, '_BUILTINS', False)
+    def test_without_builtins(self):
+        requires_yappi()
+        profile.start()
+        dict()
+        profile.stop()
+        out = read_pstats(FILENAME)
+        self.assertNotIn('__builtin__:0', out)
+
+    @MonkeyPatch(profile, 'config', make_config(enable='true'))
+    @MonkeyPatch(profile, '_FILENAME', FILENAME)
     def test_is_running(self):
         requires_yappi()
         self.assertFalse(profile.is_running())
@@ -145,6 +170,20 @@
         stats = yappi.YFuncStats()
         stats.add(FILENAME)
 
+    @MonkeyPatch(profile, 'config', make_config(enable='false'))
+    def test_with_builtins(self):
+        requires_yappi()
+        self.with_builtins()
+        out = read_pstats(FILENAME)
+        self.assertIn('__builtin__:0', out)
+
+    @MonkeyPatch(profile, 'config', make_config(enable='false'))
+    def test_without_builtins(self):
+        requires_yappi()
+        self.without_builtins()
+        out = read_pstats(FILENAME)
+        self.assertNotIn('__builtin__:0', out)
+
     @profile.profile(FILENAME)
     def profiled_function(self):
         self.assertTrue(profile.is_running())
@@ -156,3 +195,20 @@
     @profile.profile(FILENAME, format="ystat")
     def ystat_foramt(self):
         pass
+
+    @profile.profile(FILENAME)
+    def without_builtins(self):
+        pass
+
+    @profile.profile(FILENAME, builtins=True)
+    def with_builtins(self):
+        pass
+
+
+# Helpers
+
+def read_pstats(filename):
+    output = StringIO.StringIO()
+    stats = pstats.Stats(filename, stream=output)
+    stats.print_stats()
+    return stats.stream.getvalue()


-- 
To view, visit http://gerrit.ovirt.org/27787
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I67c6fc52ac64f8ff7f13471a53129a66361192ca
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <[email protected]>
_______________________________________________
vdsm-patches mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches

Reply via email to