[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