[CalendarServer-changes] [6091] CalendarServer/trunk/contrib/performance

source_changes at macosforge.org source_changes at macosforge.org
Tue Aug 17 11:09:12 PDT 2010


Revision: 6091
          http://trac.macosforge.org/projects/calendarserver/changeset/6091
Author:   exarkun at twistedmatrix.com
Date:     2010-08-17 11:09:11 -0700 (Tue, 17 Aug 2010)
Log Message:
-----------
Replace the cute context manager with something that actually works

This waits for dtrace processes to start successfully before doing the benchmark tasks, requiring
async both before and after.

Modified Paths:
--------------
    CalendarServer/trunk/contrib/performance/io_measure.d
    CalendarServer/trunk/contrib/performance/mkcal.py

Modified: CalendarServer/trunk/contrib/performance/io_measure.d
===================================================================
--- CalendarServer/trunk/contrib/performance/io_measure.d	2010-08-17 00:44:00 UTC (rev 6090)
+++ CalendarServer/trunk/contrib/performance/io_measure.d	2010-08-17 18:09:11 UTC (rev 6091)
@@ -4,7 +4,15 @@
  */
 
 #pragma D option switchrate=10hz
+#pragma D option strsize=1024
 
+dtrace:::BEGIN
+{
+	/* Let the watcher know things are alright.
+	 */
+	printf("READY\n");
+}
+
 /*
  * Low-level I/O stuff
  */

Modified: CalendarServer/trunk/contrib/performance/mkcal.py
===================================================================
--- CalendarServer/trunk/contrib/performance/mkcal.py	2010-08-17 00:44:00 UTC (rev 6090)
+++ CalendarServer/trunk/contrib/performance/mkcal.py	2010-08-17 18:09:11 UTC (rev 6091)
@@ -177,16 +177,17 @@
 
     # Now sample it a bunch of times
     data = []
-    with DTraceCollector(pids) as dtrace:
-        for i in range(samples):
-            before = time()
-            response = yield agent.request(
-                method, uri, headers, body)
-            yield readBody(response)
-            after = time()
-            data.append(after - before)
-    stats = {Duration('urlopen time'): data}
-    stats.update((yield dtrace))
+    dtrace = DTraceCollector(pids)
+    yield dtrace.start()
+    for i in range(samples):
+        before = time()
+        response = yield agent.request(
+            method, uri, headers, body)
+        yield readBody(response)
+        after = time()
+        data.append(after - before)
+    stats = yield dtrace.stop()
+    stats[Duration('urlopen time')] = data
     returnValue(stats)
 
 
@@ -229,6 +230,15 @@
     pass
 
 
+
+class DTraceBug(Exception):
+    """
+    Represents some kind of problem related to a shortcoming in dtrace
+    itself.
+    """
+
+
+
 class DTraceCollector(object):
     def __init__(self, pids):
         self.pids = pids
@@ -298,46 +308,78 @@
         self._write.append(int(rest))
 
 
-    def __enter__(self):
-        finished = []
+    def start(self):
+        ready = []
+        self.finished = []
         self.dtraces = {}
         for p in self.pids:
-            d = Deferred()
-            self.dtraces[p] = reactor.spawnProcess(
-                IOMeasureConsumer(d),
-                "/usr/sbin/dtrace",
-                ["/usr/sbin/dtrace", "-q", "-p", str(p), "-s", "io_measure.d"])
-            d.addCallback(self._cleanup, p)
-            d.addCallback(self._parse)
-            finished.append(d)
-        return gatherResults(finished).addCallback(lambda ign: self.stats())
+            started, stopped = self._startDTrace(p)
+            ready.append(started)
+            self.finished.append(stopped)
+        return gatherResults(ready)
 
 
+    def _startDTrace(self, pid):
+        started = Deferred()
+        stopped = Deferred()
+        self.dtraces[pid] = reactor.spawnProcess(
+            IOMeasureConsumer(started, stopped),
+            "/usr/sbin/dtrace",
+            ["/usr/sbin/dtrace", "-q", "-p", str(pid), "-s",
+             "io_measure.d"])
+        def eintr(reason):
+            reason.trap(DTraceBug)
+            print 'Dtrace startup failed (', reason.getErrorMessage(), '), retrying.'
+            return self._startDTrace(pid)
+        started.addErrback(eintr)
+        stopped.addCallback(self._cleanup, pid)
+        stopped.addCallback(self._parse)
+        return started, stopped
+
+
     def _cleanup(self, passthrough, pid):
         del self.dtraces[pid]
         return passthrough
 
 
-    def __exit__(self, type, value, traceback):
+    def stop(self):
         for proc in self.dtraces.itervalues():
             proc.signalProcess(SIGINT)
+        d = gatherResults(self.finished)
+        d.addCallback(lambda ign: self.stats())
+        return d
 
 
 
 class IOMeasureConsumer(ProcessProtocol):
-    def __init__(self, done):
+    def __init__(self, started, done):
+        self.started = started
         self.done = done
 
 
     def connectionMade(self):
         self.out = StringIO()
+        self._out = ''
+        self._err = ''
 
 
     def errReceived(self, bytes):
-        print bytes
+        self._err += bytes
+        if 'Interrupted system call' in self._err:
+            started = self.started
+            self.started = None
+            started.errback(DTraceBug(self._err))
 
+
     def outReceived(self, bytes):
-        self.out.write(bytes)
+        if self.started is None:
+            self.out.write(bytes)
+        else:
+            self._out += bytes
+            if self._out == 'READY\n':
+                started = self.started
+                self.started = None
+                started.callback(None)
 
 
     def processEnded(self, reason):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100817/225b349e/attachment.html>


More information about the calendarserver-changes mailing list