Francesco Romani has uploaded a new change for review.

Change subject: profile: port profiling support from VDSM
......................................................................

profile: port profiling support from VDSM

Change-Id: I5244ddcf83dc551b7139080017306e0395bcf382
Signed-off-by: Francesco Romani <[email protected]>
---
M mom/Makefile.am
A mom/Profile.py
M mom/__init__.py
M momd
4 files changed, 140 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.ovirt.org:29418/mom refs/changes/80/37780/1

diff --git a/mom/Makefile.am b/mom/Makefile.am
index c825b3f..d4d931b 100644
--- a/mom/Makefile.am
+++ b/mom/Makefile.am
@@ -32,6 +32,7 @@
        Monitor.py \
        Plotter.py \
        PolicyEngine.py \
+       Profile.py \
        RPCServer.py \
        __init__.py \
        $(NULL)
diff --git a/mom/Profile.py b/mom/Profile.py
new file mode 100644
index 0000000..b232ba0
--- /dev/null
+++ b/mom/Profile.py
@@ -0,0 +1,124 @@
+#
+# Copyright 2014-2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+
+"""
+This module provides cpu profiling.
+"""
+
+from functools import wraps
+import logging
+import os
+import threading
+
+# Import yappi lazily when profile is started
+yappi = None
+
+# Defaults
+
+_ENABLED = False
+_FILENAME = '/var/run/momd.prof'
+_FORMAT = 'pstat'
+_BUILTINS = True
+_CLOCK = 'cpu'
+_THREADS = True
+
+_lock = threading.Lock()
+
+
+class Error(Exception):
+    """ Raised when profiler is used incorrectly """
+
+
+def setup(config):
+    global _ENABLED
+    global _FILENAME
+    global _FORMAT
+    global _BUILTINS
+    global _CLOCK
+    _ENABLED = config.getboolean('devel', 'profile-enable')
+    _FILENAME = config.get('devel', 'profile-path')
+    _FORMAT = config.get('devel', 'profile-format')
+    _BUILTINS = config.getboolean('devel', 'profile-builtins')
+    _CLOCK = config.get('devel', 'profile-clock')
+
+
+def start():
+    """ Starts application wide profiling """
+    if is_enabled():
+        _start_profiling(_CLOCK, _BUILTINS, _THREADS)
+
+
+def stop():
+    """ Stops application wide profiling """
+    if is_enabled():
+        _stop_profiling(_FILENAME, _FORMAT)
+
+
+def is_enabled():
+    return _ENABLED
+
+
+def is_running():
+    with _lock:
+        return yappi and yappi.is_running()
+
+
+def profile(filename, format=_FORMAT, clock=_CLOCK, builtins=_BUILTINS,
+            threads=_THREADS):
+    """
+    Profile decorated function, saving profile to filename using format.
+
+    Note: you cannot use this when the application wide profile is enabled, or
+    profile multiple functions in the same code path.
+    """
+    def decorator(f):
+        @wraps(f)
+        def wrapper(*a, **kw):
+            _start_profiling(clock, builtins, threads)
+            try:
+                return f(*a, **kw)
+            finally:
+                _stop_profiling(filename, format)
+        return wrapper
+    return decorator
+
+
+def _start_profiling(clock, builtins, threads):
+    global yappi
+    logging.debug("Starting profiling")
+    with _lock:
+        import yappi
+        # yappi start semantics are a bit too liberal, returning success if
+        # yappi is already started, happily having too different code paths
+        # that thinks they own the single process profiler.
+        if yappi.is_running():
+            raise Error('Profiler is already running')
+        yappi.set_clock_type(clock)
+        yappi.start(builtins=builtins, profile_threads=threads)
+
+
+def _stop_profiling(filename, format):
+    logging.debug("Stopping profiling")
+    with _lock:
+        if yappi.is_running():
+            yappi.stop()
+            stats = yappi.get_func_stats()
+            stats.save(filename, format)
+            yappi.clear_stats()
diff --git a/mom/__init__.py b/mom/__init__.py
index dbb0c68..46672df 100644
--- a/mom/__init__.py
+++ b/mom/__init__.py
@@ -10,6 +10,7 @@
 from mom.PolicyEngine import PolicyEngine
 from mom.RPCServer import RPCServer
 from mom.MOMFuncs import MOMFuncs, EXPORTED_ATTRIBUTE
+from . import Profile
 
 
 def load_config(fname, overrides=None):
@@ -39,6 +40,12 @@
     config.set('host', 'collectors', 'HostMemory')
     config.add_section('guest')
     config.set('guest', 'collectors', 'GuestQemuProc, GuestMemory')
+    config.add_section('devel')
+    config.set('devel', 'profile-enable', 'false')
+    config.set('devel', 'profile-path', '/var/run/momd.prof')
+    config.set('devel', 'profile-format', 'pstat')
+    config.set('devel', 'profile-builtins', 'true')
+    config.set('devel', 'profile-clock', 'cpu')
 
     # Override defaults from the config file
     config.read(fname)
diff --git a/momd b/momd
index aaa5a89..efb7f77 100755
--- a/momd
+++ b/momd
@@ -129,7 +129,14 @@
 
     conf_data = mom.load_config(options.config_file, config_overrides)
     mom_instance = mom.MOM.from_config(conf_data)
-    mom_instance.run()
+    mom.Profile.setup(conf_data)
+    mom.Profile.start()
+    try:
+        mom_instance.run()
+    except Exception:
+        raise
+    finally:
+        mom.Profile.stop()
     sys.exit(0)
 
 if __name__ == "__main__":


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I5244ddcf83dc551b7139080017306e0395bcf382
Gerrit-PatchSet: 1
Gerrit-Project: mom
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to