[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