[Erp5-report] r46032 jm - /erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequest...

nobody at svn.erp5.org nobody at svn.erp5.org
Fri Nov 18 15:28:36 CET 2011


Author: jm
Date: Fri Nov 18 15:28:35 2011
New Revision: 46032

URL: http://svn.erp5.org?rev=46032&view=rev
Log:
LongRequestLogger: optimize way to have an interruptible sleep

On some hardware like VMWare VM, threading.Condition objects are very
unefficient when used with a timeout.

API of Monitor class is also changed to avoid recreating a pipe object on each
request.

Modified:
    erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/monitor.py
    erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/patch.py

Modified: erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/monitor.py
URL: http://svn.erp5.org/erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/monitor.py?rev=46032&r1=46031&r2=46032&view=diff
==============================================================================
--- erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/monitor.py [utf8] (original)
+++ erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/monitor.py [utf8] Fri Nov 18 15:28:35 2011
@@ -4,59 +4,53 @@
 #
 ##############################################################################
 
+import fcntl, os
+from select import select
 from threading import Thread
-from threading import Condition
 from Products.LongRequestLogger import dumper
 
 class Monitor(Thread):
     """Logs the stack-trace of a thread until it's stopped
 
-    m = Monitor(thread.get_ident(), timeout=5, interval=2)
+    m = Monitor()
+    m.start(thread.get_ident(), timeout=5, interval=2)
 
     Wait 5 seconds before dumping the stack-trace of the identified thread
     every 2 seconds.
 
     m.stop()
-    
+
     Stop the monitoring, whether timed-out or not
-    """
 
-    running = False
+    XXX: signal.pthread_kill should be better than a pipe,
+         but it's new to Python 3.3
+    """
 
-    def __init__(self,
-                 thread_id=None,
-                 timeout=None,
-                 interval=None):
+    def __init__(self):
         Thread.__init__(self)
+        self._event_pipe =  os.pipe()
+        r = self._event_pipe[0]
+        f = fcntl.fcntl(r, fcntl.F_GETFL, 0)
+        fcntl.fcntl(r, fcntl.F_SETFL, f | os.O_NONBLOCK)
+
+    def start(self, thread_id=None, timeout=None, interval=None):
         self.dumper = dumper.Dumper(thread_id=thread_id)
         self.timeout = timeout or self.dumper.timeout
         self.interval = interval or self.dumper.interval
-        self.running_condition = Condition()
         if self.dumper.is_enabled():
-            self.running = True
-            self.start()
+            Thread.start(self)
 
     def stop(self):
         """Stop monitoring the other thread"""
-        # this function is called by the other thread, when it wants to stop
-        # being monitored
-        self.running_condition.acquire()
-        try:
-            if not self.running:
-                return # yes, the finally clause will be run, don't worry
-            self.running = False
-            self.running_condition.notify()
-        finally:
-            self.running_condition.release()
-        self.join()
+        if self.is_alive():
+            os.write(self._event_pipe[1], '\0')
+            self.join()
+            Thread.__init__(self)
 
     def run(self):
-        self.running_condition.acquire()
-        self.running_condition.wait(self.timeout)
-        # If the other thread is still running by now, it's time to monitor it
-        try:
-            while self.running:
-                self.dumper()
-                self.running_condition.wait(self.interval)
-        finally:
-            self.running_condition.release()
+        r = self._event_pipe[0]
+        timeout = self.timeout
+        while not select([r], [], [], timeout)[0]:
+            self.dumper()
+            timeout = self.interval
+        os.read(r, 1)

Modified: erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/patch.py
URL: http://svn.erp5.org/erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/patch.py?rev=46032&r1=46031&r2=46032&view=diff
==============================================================================
--- erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/patch.py [utf8] (original)
+++ erp5/trunk/utils/Products.LongRequestLogger/Products/LongRequestLogger/patch.py [utf8] Fri Nov 18 15:28:35 2011
@@ -10,13 +10,13 @@ from Products.LongRequestLogger.monitor 
 
 log = getLogger(__name__)
 
+monitor = Monitor()
 def wrapper(*args, **kw):
-    m = Monitor()
+    monitor.start()
     try:
-        result = wrapper.original(*args, **kw)
-        return result
+        return wrapper.original(*args, **kw)
     finally:
-        m.stop()
+        monitor.stop()
 
 def do_patch():
     from ZPublisher.Publish import publish_module_standard as original



More information about the Erp5-report mailing list