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

source_changes at macosforge.org source_changes at macosforge.org
Thu Aug 19 17:59:40 PDT 2010


Revision: 6142
          http://trac.macosforge.org/projects/calendarserver/changeset/6142
Author:   exarkun at twistedmatrix.com
Date:     2010-08-19 17:59:39 -0700 (Thu, 19 Aug 2010)
Log Message:
-----------
add a second benchmark, this one for event creation, and refactor the existing benchmark to share code with it

Modified Paths:
--------------
    CalendarServer/trunk/contrib/performance/vfreebusy.py

Added Paths:
-----------
    CalendarServer/trunk/contrib/performance/event.py
    CalendarServer/trunk/contrib/performance/httpclient.py

Added: CalendarServer/trunk/contrib/performance/event.py
===================================================================
--- CalendarServer/trunk/contrib/performance/event.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/event.py	2010-08-20 00:59:39 UTC (rev 6142)
@@ -0,0 +1,124 @@
+
+"""
+Benchmark a server's handling of event creation and modification.
+"""
+
+from itertools import count
+
+from urllib2 import HTTPDigestAuthHandler
+from uuid import uuid4
+from datetime import datetime, timedelta
+
+from twisted.internet import reactor
+from twisted.web.client import Agent
+from twisted.web.http_headers import Headers
+
+from httpauth import AuthHandlerAgent
+from httpclient import StringProducer
+from benchlib import initialize, sample
+
+# XXX Represent these as vobjects?  Would make it easier to add more vevents.
+event = """\
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+BEGIN:VTIMEZONE
+TZID:America/Los_Angeles
+BEGIN:STANDARD
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+TZNAME:PST
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0800
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+TZNAME:PDT
+TZOFFSETFROM:-0800
+TZOFFSETTO:-0700
+END:DAYLIGHT
+END:VTIMEZONE
+%(VEVENTS)s\
+END:VCALENDAR
+"""
+
+attendee = """\
+ATTENDEE;CN=User %(SEQUENCE)02d;CUTYPE=INDIVIDUAL;EMAIL=user%(SEQUENCE)02d at example.com;PARTSTAT=NE
+ EDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:use
+ r%(SEQUENCE)02d
+"""
+
+def makeAttendees(count):
+    return '\n'.join([
+            attendee % {'SEQUENCE': n} for n in range(2, count + 2)])
+
+
+def formatDate(d):
+    return ''.join(filter(str.isalnum, d.isoformat()))
+
+
+def makeEvent(i, attendeeCount):
+    s = """\
+BEGIN:VEVENT
+UID:%(UID)s
+DTSTART;TZID=America/Los_Angeles:%(START)s
+DTEND;TZID=America/Los_Angeles:%(END)s
+%(ATTENDEES)s\
+CREATED:20100729T193912Z
+DTSTAMP:20100729T195557Z
+ORGANIZER;CN=User 03;EMAIL=user03 at example.com:urn:uuid:user03
+SEQUENCE:%(SEQUENCE)s
+SUMMARY:STUFF IS THINGS
+TRANSP:OPAQUE
+END:VEVENT
+"""
+    base = datetime(2010, 7, 30, 11, 15, 00)
+    interval = timedelta(0, 5)
+    duration = timedelta(0, 3)
+    return event % {
+        'VEVENTS': s % {
+            'UID': uuid4(),
+            'START': formatDate(base + i * interval),
+            'END': formatDate(base + i * interval + duration),
+            'SEQUENCE': i,
+            'ATTENDEES': makeAttendees(attendeeCount),
+            },
+        }
+
+
+def measure(dtrace, attendeeCount, samples):
+    user = password = "user01"
+    host = "localhost"
+    port = 8008
+    root = "/"
+    principal = "/"
+    calendar = "event-creation-benchmark"
+
+    # First set things up
+    initialize(host, port, user, password, root, principal, calendar)
+
+    # CalDAVClientLibrary can't seem to POST things.  Use Twisted instead.
+    authinfo = HTTPDigestAuthHandler()
+    authinfo.add_password(
+        realm="Test Realm",
+        uri="http://%s:%d/" % (host, port),
+        user=user,
+        passwd=password)
+
+    agent = AuthHandlerAgent(Agent(reactor), authinfo)
+    method = 'PUT'
+    uri = 'http://%s:%d/calendars/__uids__/%s/%s/foo-%%d.ics' % (
+        host, port, user, calendar)
+    headers = Headers({"content-type": ["text/calendar"]})
+
+    # An infinite stream of VEVENTs to PUT to the server.
+    events = ((i, makeEvent(i, attendeeCount)) for i in count(2))
+
+    # Sample it a bunch of times
+    return sample(
+        dtrace, samples, 
+        agent, ((method, uri % (i,), headers, StringProducer(body))
+                for (i, body)
+                in events).next)

Added: CalendarServer/trunk/contrib/performance/httpclient.py
===================================================================
--- CalendarServer/trunk/contrib/performance/httpclient.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/httpclient.py	2010-08-20 00:59:39 UTC (rev 6142)
@@ -0,0 +1,41 @@
+
+from zope.interface import implements
+
+from twisted.internet.protocol import Protocol
+from twisted.internet.defer import Deferred, succeed
+from twisted.web.iweb import IBodyProducer
+
+class _DiscardReader(Protocol):
+    def __init__(self, finished):
+        self.finished = finished
+
+
+    def dataReceived(self, bytes):
+        pass
+
+
+    def connectionLost(self, reason):
+        self.finished.callback(None)
+
+
+
+def readBody(response):
+    finished = Deferred()
+    response.deliverBody(_DiscardReader(finished))
+    return finished
+
+
+
+class StringProducer(object):
+    implements(IBodyProducer)
+
+    def __init__(self, body):
+        self._body = body
+        self.length = len(self._body)
+
+
+    def startProducing(self, consumer):
+        consumer.write(self._body)
+        return succeed(None)
+
+

Modified: CalendarServer/trunk/contrib/performance/vfreebusy.py
===================================================================
--- CalendarServer/trunk/contrib/performance/vfreebusy.py	2010-08-20 00:59:00 UTC (rev 6141)
+++ CalendarServer/trunk/contrib/performance/vfreebusy.py	2010-08-20 00:59:39 UTC (rev 6142)
@@ -5,25 +5,19 @@
 from urllib2 import HTTPDigestAuthHandler
 from uuid import uuid4
 from datetime import datetime, timedelta
-from time import time
 
-from client.account import CalDAVAccount
 from protocol.url import URL
 
-from zope.interface import implements
-
-from twisted.internet.protocol import Protocol
 from twisted.internet.defer import (
-    Deferred, inlineCallbacks, returnValue, succeed)
+    inlineCallbacks)
 from twisted.internet import reactor
-from twisted.web.iweb import IBodyProducer
 from twisted.web.client import Agent
 from twisted.web.http_headers import Headers
 
 from httpauth import AuthHandlerAgent
-from stats import Duration
+from httpclient import StringProducer
+from benchlib import initialize, sample
 
-
 # XXX Represent these as vobjects?  Would make it easier to add more vevents.
 event = """\
 BEGIN:VCALENDAR
@@ -103,63 +97,29 @@
     return [makeEvent(i) for i in range(n)]
 
 
-class _DiscardReader(Protocol):
-    def __init__(self, finished):
-        self.finished = finished
-
-
-    def dataReceived(self, bytes):
-        pass
-
-
-    def connectionLost(self, reason):
-        self.finished.callback(None)
-
-
-
-def readBody(response):
-    finished = Deferred()
-    response.deliverBody(_DiscardReader(finished))
-    return finished
-
-
-
-class StringProducer(object):
-    implements(IBodyProducer)
-
-    def __init__(self, body):
-        self._body = body
-        self.length = len(self._body)
-
-
-    def startProducing(self, consumer):
-        consumer.write(self._body)
-        return succeed(None)
-
-
- at inlineCallbacks
 def measure(dtrace, events, samples):
+    user = password = "user01"
+    host = "localhost"
+    port = 8008
+    root = "/"
+    principal = "/"
+    calendar = "vfreebusy-benchmark"
+
     # First set things up
-    account = CalDAVAccount(
-        "localhost:8008", user="user01", pswd="user01", root="/", principal="/")
-    account.session.deleteResource(
-        URL("/calendars/users/user01/monkeys3/"))
-    account.session.makeCalendar(
-        URL("/calendars/users/user01/monkeys3/"))
+    account = initialize(host, port, user, password, root, principal, calendar)
 
+    base = "/calendars/users/%s/%s/foo-%%d.ics" % (user, calendar)
     for i, cal in enumerate(makeEvents(events)):
         account.session.writeData(
-            URL("/calendars/users/user01/monkeys3/foo-%d.ics" % (i,)),
-            cal,
-            "text/calendar")
+            URL(base % (i,)), cal, "text/calendar")
 
     # CalDAVClientLibrary can't seem to POST things.
     authinfo = HTTPDigestAuthHandler()
     authinfo.add_password(
         realm="Test Realm",
-        uri="http://localhost:8008/",
-        user="user01",
-        passwd="user01")
+        uri="http://%s:%d/" % (host, port),
+        user=user,
+        passwd=password)
 
     agent = AuthHandlerAgent(Agent(reactor), authinfo)
     method = 'POST'
@@ -167,16 +127,6 @@
     headers = Headers({"content-type": ["text/calendar"]})
     body = StringProducer(vfreebusy)
 
-    # Now sample it a bunch of times
-    data = []
-    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)
+    return sample(
+        dtrace, samples, 
+        agent, lambda: (method, uri, headers, body))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100819/87294d7b/attachment-0001.html>


More information about the calendarserver-changes mailing list