[CalendarServer-changes] [9429] CalendarServer/trunk/contrib/performance
source_changes at macosforge.org
source_changes at macosforge.org
Wed Jul 11 10:07:28 PDT 2012
Revision: 9429
http://trac.macosforge.org/projects/calendarserver/changeset/9429
Author: cdaboo at apple.com
Date: 2012-07-11 10:07:27 -0700 (Wed, 11 Jul 2012)
Log Message:
-----------
Add the ability for the sim tool to generate recurring events with various RRULE patterns based on a distribution.
Modified Paths:
--------------
CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist
CalendarServer/trunk/contrib/performance/loadtest/config.plist
CalendarServer/trunk/contrib/performance/loadtest/ical.py
CalendarServer/trunk/contrib/performance/loadtest/profiles.py
CalendarServer/trunk/contrib/performance/stats.py
CalendarServer/trunk/contrib/performance/test_stats.py
Modified: CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist 2012-07-11 01:17:35 UTC (rev 9428)
+++ CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist 2012-07-11 17:07:27 UTC (rev 9429)
@@ -210,6 +210,52 @@
<string>America/Los_Angeles</string>
</dict>
</dict>
+
+ <!-- Define how recurrences are created. -->
+ <key>recurrenceDistribution</key>
+ <dict>
+
+ <!-- This distribution is pretty specialized. We have a fixed set of
+ RRULEs defined for this distribution and pick each based on a
+ weight. -->
+ <key>type</key>
+ <string>contrib.performance.stats.RecurrenceDistribution</string>
+
+ <key>params</key>
+ <dict>
+ <!-- False to disable RRULEs -->
+ <key>allowRecurrence</key>
+ <true/>
+
+ <!-- These are the weights for the specific set of RRULEs. -->
+ <key>weights</key>
+ <dict>
+ <!-- Half of all events will be non-recurring -->
+ <key>none</key>
+ <integer>50</integer>
+
+ <!-- Daily and weekly are pretty common -->
+ <key>daily</key>
+ <integer>10</integer>
+ <key>weekly</key>
+ <integer>20</integer>
+
+ <!-- Monthly, yearly, daily & weekly limit not so common -->
+ <key>monthly</key>
+ <integer>2</integer>
+ <key>yearly</key>
+ <integer>1</integer>
+ <key>dailylimit</key>
+ <integer>2</integer>
+ <key>weeklylimit</key>
+ <integer>5</integer>
+
+ <!-- Work days pretty common -->
+ <key>workdays</key>
+ <integer>10</integer>
+ </dict>
+ </dict>
+ </dict>
</dict>
</dict>
@@ -336,8 +382,8 @@
<!-- maximum -->
<key>maximum</key>
<real>100</real>
- </dict>
- </dict>
+ </dict>
+ </dict>
<!-- Define how start times (DTSTART) for the randomly generated events
will be selected. This is an example of a "Distribution" parameter. The value
@@ -378,6 +424,52 @@
<string>America/Los_Angeles</string>
</dict>
</dict>
+
+ <!-- Define how recurrences are created. -->
+ <key>recurrenceDistribution</key>
+ <dict>
+
+ <!-- This distribution is pretty specialized. We have a fixed set of
+ RRULEs defined for this distribution and pick each based on a
+ weight. -->
+ <key>type</key>
+ <string>contrib.performance.stats.RecurrenceDistribution</string>
+
+ <key>params</key>
+ <dict>
+ <!-- False to disable RRULEs -->
+ <key>allowRecurrence</key>
+ <true/>
+
+ <!-- These are the weights for the specific set of RRULEs. -->
+ <key>weights</key>
+ <dict>
+ <!-- Half of all events will be non-recurring -->
+ <key>none</key>
+ <integer>50</integer>
+
+ <!-- Daily and weekly are pretty common -->
+ <key>daily</key>
+ <integer>10</integer>
+ <key>weekly</key>
+ <integer>20</integer>
+
+ <!-- Monthly, yearly, daily & weekly limit not so common -->
+ <key>monthly</key>
+ <integer>2</integer>
+ <key>yearly</key>
+ <integer>1</integer>
+ <key>dailylimit</key>
+ <integer>2</integer>
+ <key>weeklylimit</key>
+ <integer>5</integer>
+
+ <!-- Work days pretty common -->
+ <key>workdays</key>
+ <integer>10</integer>
+ </dict>
+ </dict>
+ </dict>
</dict>
</dict>
Modified: CalendarServer/trunk/contrib/performance/loadtest/config.plist
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/config.plist 2012-07-11 01:17:35 UTC (rev 9428)
+++ CalendarServer/trunk/contrib/performance/loadtest/config.plist 2012-07-11 17:07:27 UTC (rev 9429)
@@ -204,6 +204,52 @@
<string>America/Los_Angeles</string>
</dict>
</dict>
+
+ <!-- Define how recurrences are created. -->
+ <key>recurrenceDistribution</key>
+ <dict>
+
+ <!-- This distribution is pretty specialized. We have a fixed set of
+ RRULEs defined for this distribution and pick each based on a
+ weight. -->
+ <key>type</key>
+ <string>contrib.performance.stats.RecurrenceDistribution</string>
+
+ <key>params</key>
+ <dict>
+ <!-- False to disable RRULEs -->
+ <key>allowRecurrence</key>
+ <true/>
+
+ <!-- These are the weights for the specific set of RRULEs. -->
+ <key>weights</key>
+ <dict>
+ <!-- Half of all events will be non-recurring -->
+ <key>none</key>
+ <integer>50</integer>
+
+ <!-- Daily and weekly are pretty common -->
+ <key>daily</key>
+ <integer>10</integer>
+ <key>weekly</key>
+ <integer>20</integer>
+
+ <!-- Monthly, yearly, daily & weekly limit not so common -->
+ <key>monthly</key>
+ <integer>2</integer>
+ <key>yearly</key>
+ <integer>1</integer>
+ <key>dailylimit</key>
+ <integer>2</integer>
+ <key>weeklylimit</key>
+ <integer>5</integer>
+
+ <!-- Work days pretty common -->
+ <key>workdays</key>
+ <integer>10</integer>
+ </dict>
+ </dict>
+ </dict>
</dict>
</dict>
@@ -372,6 +418,52 @@
<string>America/Los_Angeles</string>
</dict>
</dict>
+
+ <!-- Define how recurrences are created. -->
+ <key>recurrenceDistribution</key>
+ <dict>
+
+ <!-- This distribution is pretty specialized. We have a fixed set of
+ RRULEs defined for this distribution and pick each based on a
+ weight. -->
+ <key>type</key>
+ <string>contrib.performance.stats.RecurrenceDistribution</string>
+
+ <key>params</key>
+ <dict>
+ <!-- False to disable RRULEs -->
+ <key>allowRecurrence</key>
+ <true/>
+
+ <!-- These are the weights for the specific set of RRULEs. -->
+ <key>weights</key>
+ <dict>
+ <!-- Half of all events will be non-recurring -->
+ <key>none</key>
+ <integer>50</integer>
+
+ <!-- Daily and weekly are pretty common -->
+ <key>daily</key>
+ <integer>10</integer>
+ <key>weekly</key>
+ <integer>20</integer>
+
+ <!-- Monthly, yearly, daily & weekly limit not so common -->
+ <key>monthly</key>
+ <integer>2</integer>
+ <key>yearly</key>
+ <integer>1</integer>
+ <key>dailylimit</key>
+ <integer>2</integer>
+ <key>weeklylimit</key>
+ <integer>5</integer>
+
+ <!-- Work days pretty common -->
+ <key>workdays</key>
+ <integer>10</integer>
+ </dict>
+ </dict>
+ </dict>
</dict>
</dict>
Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/ical.py 2012-07-11 01:17:35 UTC (rev 9428)
+++ CalendarServer/trunk/contrib/performance/loadtest/ical.py 2012-07-11 17:07:27 UTC (rev 9429)
@@ -342,7 +342,7 @@
calendarHomePollInterval=None,
supportPush=True,
supportAmpPush=True,
- ampPushHost="localhost",
+ ampPushHost=None,
ampPushPort=62311,
):
@@ -366,6 +366,8 @@
self.supportPush = supportPush
self.supportAmpPush = supportAmpPush
+ if ampPushHost is None:
+ ampPushHost = urlparse(self.root)[1].split(":")[0]
self.ampPushHost = ampPushHost
self.ampPushPort = ampPushPort
@@ -886,7 +888,11 @@
multistatus = yield self._eventReport(calendar.url, batchedHrefs)
for responseHref in batchedHrefs:
- res = multistatus[responseHref]
+ try:
+ res = multistatus[responseHref]
+ except KeyError:
+ # Resource might have been deleted
+ continue
if res.getStatus() == 200:
text = res.getTextProperties()
etag = text[davxml.getetag]
Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/profiles.py 2012-07-11 01:17:35 UTC (rev 9428)
+++ CalendarServer/trunk/contrib/performance/loadtest/profiles.py 2012-07-11 17:07:27 UTC (rev 9429)
@@ -37,7 +37,7 @@
from twistedcaldav.ical import Property, Component
from contrib.performance.stats import NearFutureDistribution, NormalDistribution, UniformDiscreteDistribution, mean, median
-from contrib.performance.stats import LogNormalDistribution
+from contrib.performance.stats import LogNormalDistribution, RecurrenceDistribution
from contrib.performance.loadtest.logger import SummarizingMixin
from contrib.performance.loadtest.ical import IncorrectResponseCode
@@ -298,7 +298,8 @@
15 * 60, 30 * 60,
45 * 60, 60 * 60,
120 * 60
- ])
+ ]),
+ recurrenceDistribution=RecurrenceDistribution(False),
):
self.enabled = enabled
self._sendInvitationDistribution = sendInvitationDistribution
@@ -306,6 +307,7 @@
self._inviteeCountDistribution = inviteeCountDistribution
self._eventStartDistribution = eventStartDistribution
self._eventDurationDistribution = eventDurationDistribution
+ self._recurrenceDistribution = recurrenceDistribution
def run(self):
@@ -386,6 +388,10 @@
vevent.replaceProperty(Property("DTSTART", dtstart))
vevent.replaceProperty(Property("DTEND", dtend))
vevent.replaceProperty(Property("UID", uid))
+
+ rrule = self._recurrenceDistribution.sample()
+ if rrule is not None:
+ vevent.addProperty(Property(None, None, None, pycalendar=rrule))
vevent.addProperty(self._client._makeSelfOrganizer())
vevent.addProperty(self._client._makeSelfAttendee())
@@ -582,12 +588,14 @@
15 * 60, 30 * 60,
45 * 60, 60 * 60,
120 * 60
- ])
+ ]),
+ recurrenceDistribution=RecurrenceDistribution(False),
):
self.enabled = enabled
self._interval = interval
self._eventStartDistribution = eventStartDistribution
self._eventDurationDistribution = eventDurationDistribution
+ self._recurrenceDistribution = recurrenceDistribution
def run(self):
@@ -618,6 +626,10 @@
vevent.replaceProperty(Property("DTSTART", dtstart))
vevent.replaceProperty(Property("DTEND", dtend))
vevent.replaceProperty(Property("UID", uid))
+
+ rrule = self._recurrenceDistribution.sample()
+ if rrule is not None:
+ vevent.addProperty(Property(None, None, None, pycalendar=rrule))
href = '%s%s.ics' % (calendar.url, uid)
d = self._client.addEvent(href, vcalendar)
Modified: CalendarServer/trunk/contrib/performance/stats.py
===================================================================
--- CalendarServer/trunk/contrib/performance/stats.py 2012-07-11 01:17:35 UTC (rev 9428)
+++ CalendarServer/trunk/contrib/performance/stats.py 2012-07-11 17:07:27 UTC (rev 9429)
@@ -24,6 +24,7 @@
from pycalendar.datetime import PyCalendarDateTime
from pycalendar.duration import PyCalendarDuration
from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.property import PyCalendarProperty
NANO = 1000000000.0
@@ -222,7 +223,7 @@
class IPopulation(Interface):
- def sample():
+ def sample(): #@NoSelf
pass
@@ -234,14 +235,16 @@
compareAttributes = ['_values']
- def __init__(self, values):
+ def __init__(self, values, randomize=True):
self._values = values
+ self._randomize = randomize
self._refill()
def _refill(self):
self._remaining = self._values[:]
- random.shuffle(self._remaining)
+ if self._randomize:
+ random.shuffle(self._remaining)
def sample(self):
@@ -378,6 +381,42 @@
offset.setDuration(offset.getTotalSeconds() - (end - start).getTotalSeconds())
beginning = end
+class RecurrenceDistribution(object, FancyEqMixin):
+ compareAttributes = ["_allowRecurrence", "_weights"]
+
+ _model_rrules = {
+ "none": None,
+ "daily": "RRULE:FREQ=DAILY",
+ "weekly": "RRULE:FREQ=WEEKLY",
+ "monthly": "RRULE:FREQ=MONTHLY",
+ "yearly": "RRULE:FREQ=YEARLY",
+ "dailylimit": "RRULE:FREQ=DAILY;COUNT=14",
+ "weeklylimit": "RRULE:FREQ=WEEKLY;COUNT=4",
+ "workdays": "RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR"
+ }
+
+ def __init__(self, allowRecurrence, weights={}):
+ self._allowRecurrence = allowRecurrence
+ self._rrules = []
+ if self._allowRecurrence:
+ for rrule, count in sorted(weights.items(), key=lambda x:x[0]):
+ for _ignore in range(count):
+ self._rrules.append(self._model_rrules[rrule])
+ self._helperDistribution = UniformIntegerDistribution(0, len(self._rrules)-1)
+
+
+ def sample(self):
+
+ if self._allowRecurrence:
+ index = self._helperDistribution.sample()
+ rrule = self._rrules[index]
+ if rrule:
+ prop = PyCalendarProperty()
+ prop.parse(rrule)
+ return prop
+
+ return None
+
if __name__ == '__main__':
from collections import defaultdict
Modified: CalendarServer/trunk/contrib/performance/test_stats.py
===================================================================
--- CalendarServer/trunk/contrib/performance/test_stats.py 2012-07-11 01:17:35 UTC (rev 9428)
+++ CalendarServer/trunk/contrib/performance/test_stats.py 2012-07-11 17:07:27 UTC (rev 9429)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2010 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2012 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,7 +18,8 @@
from stats import (
SQLDuration, LogNormalDistribution, UniformDiscreteDistribution,
- UniformIntegerDistribution, WorkDistribution, quantize)
+ UniformIntegerDistribution, WorkDistribution, quantize,
+ RecurrenceDistribution)
from pycalendar.datetime import PyCalendarDateTime
from pycalendar.timezone import PyCalendarTimezone
@@ -91,6 +92,25 @@
#test_workdistribution.todo = "Somehow timezones mess this up"
+ def test_recurrencedistribution(self):
+ dist = RecurrenceDistribution(False)
+ for _ignore in range(100):
+ value = dist.sample()
+ self.assertTrue(value is None)
+
+ dist = RecurrenceDistribution(True, {"daily":1, "none":2, "weekly":1})
+ dist._helperDistribution = UniformDiscreteDistribution([0, 3, 2, 1, 0], randomize=False)
+ value = dist.sample()
+ self.assertTrue(value is not None)
+ value = dist.sample()
+ self.assertTrue(value is None)
+ value = dist.sample()
+ self.assertTrue(value is None)
+ value = dist.sample()
+ self.assertTrue(value is not None)
+ value = dist.sample()
+ self.assertTrue(value is not None)
+
def test_uniform(self):
dist = UniformIntegerDistribution(-5, 10)
for _ignore_i in range(100):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120711/cc6aa5af/attachment-0001.html>
More information about the calendarserver-changes
mailing list