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

source_changes at macosforge.org source_changes at macosforge.org
Thu May 26 13:13:40 PDT 2011


Revision: 7531
          http://trac.macosforge.org/projects/calendarserver/changeset/7531
Author:   exarkun at twistedmatrix.com
Date:     2011-05-26 13:13:40 -0700 (Thu, 26 May 2011)
Log Message:
-----------
Add ability to pass parameters to profile objects; move hard-coded timing/etc constants out of profile implementations and into config plist

Modified Paths:
--------------
    CalendarServer/trunk/contrib/performance/loadtest/config.plist
    CalendarServer/trunk/contrib/performance/loadtest/population.py
    CalendarServer/trunk/contrib/performance/loadtest/profiles.py
    CalendarServer/trunk/contrib/performance/loadtest/sim.py
    CalendarServer/trunk/contrib/performance/loadtest/test_sim.py
    CalendarServer/trunk/contrib/performance/run.sh
    CalendarServer/trunk/contrib/performance/stats.py
    CalendarServer/trunk/contrib/performance/test_stats.py
    CalendarServer/trunk/contrib/performance/todo

Modified: CalendarServer/trunk/contrib/performance/loadtest/config.plist
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/config.plist	2011-05-26 20:08:42 UTC (rev 7530)
+++ CalendarServer/trunk/contrib/performance/loadtest/config.plist	2011-05-26 20:13:40 UTC (rev 7531)
@@ -64,9 +64,46 @@
 
 	<key>profiles</key>
 	<array>
-	  <string>loadtest.profiles.Eventer</string>
-	  <string>loadtest.profiles.Inviter</string>
-	  <string>loadtest.profiles.Accepter</string>
+
+	  <dict>
+	    <key>class</key>
+	    <string>loadtest.profiles.Eventer</string>
+
+	    <key>params</key>
+	    <dict>
+	      <key>interval</key>
+	      <integer>25</integer>
+	    </dict>
+	  </dict>
+
+	  <dict>
+	    <key>class</key>
+	    <string>loadtest.profiles.Inviter</string>
+
+	    <key>params</key>
+	    <dict>
+	      <key>interval</key>
+	      <integer>20</integer>
+
+	      <key>spread</key>
+	      <integer>3</integer>
+	    </dict>
+	  </dict>
+
+	  <dict>
+	    <key>class</key>
+	    <string>loadtest.profiles.Accepter</string>
+
+	    <key>params</key>
+	    <dict>
+	      <key>delay</key>
+	      <integer>10</integer>
+
+	      <key>spread</key>
+	      <integer>2</integer>
+	    </dict>
+	  </dict>
+
 	</array>
 
 	<key>weight</key>

Modified: CalendarServer/trunk/contrib/performance/loadtest/population.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/population.py	2011-05-26 20:08:42 UTC (rev 7530)
+++ CalendarServer/trunk/contrib/performance/loadtest/population.py	2011-05-26 20:13:40 UTC (rev 7531)
@@ -33,10 +33,31 @@
 from loadtest.ical import SnowLeopard, RequestLogger
 from loadtest.profiles import Eventer, Inviter, Accepter
 
+
+class ProfileType(object, FancyEqMixin):
+    """
+    @ivar profileType: A L{ProfileBase} subclass, or an L{ICalendarUserProfile}
+        implementation.
+
+    @ivar params: A C{dict} which will be passed to C{profileType} as keyword
+        arguments to create a new profile instance.
+    """
+    compareAttributes = ("profileType", "params")
+
+    def __init__(self, profileType, params):
+        self.profileType = profileType
+        self.params = params
+
+
+    def __call__(self, reactor, client, number):
+        return self.profileType(reactor, client, number, **self.params)
+
+
+
 class ClientType(object, FancyEqMixin):
     """
     @ivar clientType: An L{ICalendarClient} implementation
-    @ivar profileTypes: A list of L{ICalendarUserProfile} implementations
+    @ivar profileTypes: A list of L{ProfileType} instances
     """
     compareAttributes = ("clientType", "profileTypes")
 

Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/profiles.py	2011-05-26 20:08:42 UTC (rev 7530)
+++ CalendarServer/trunk/contrib/performance/loadtest/profiles.py	2011-05-26 20:13:40 UTC (rev 7531)
@@ -49,12 +49,17 @@
     """
     random = random
 
-    def __init__(self, reactor, client, userNumber):
+    def __init__(self, reactor, client, userNumber, **params):
         self._reactor = reactor
         self._client = client
         self._number = userNumber
+        self.setParameters(**params)
 
 
+    def setParameters(self):
+        pass
+
+
     def _calendarsOfType(self, calendarType):
         return [
             cal 
@@ -109,11 +114,15 @@
     """
     A Calendar user who invites and de-invites other users to events.
     """
+    def setParameters(self, interval=20, spread=3):
+        self._interval = interval
+        self._spread = spread
+
+
     def run(self):
         self._call = LoopingCall(self._invite)
         self._call.clock = self._reactor
-        # XXX Base this on something real
-        return self._call.start(20)
+        return self._call.start(self._interval)
 
 
     def _addAttendee(self, event, attendees):
@@ -126,7 +135,7 @@
             invitees.add(att.value)
 
         for i in range(10):
-            invitee = max(1, int(self.random.gauss(self._number, 3)))
+            invitee = max(1, int(self.random.gauss(self._number, self._spread)))
             uuid = u'urn:uuid:user%02d' % (invitee,)
             if uuid not in invitees:
                 break
@@ -207,10 +216,10 @@
     """
     A Calendar user who accepts invitations to events.
     """
-
-    def __init__(self, reactor, client, userNumber):
-        ProfileBase.__init__(self, reactor, client, userNumber)
+    def setParameters(self, delay=10, spread=2):
         self._accepting = set()
+        self._delay = delay
+        self._spread = spread
 
 
     def run(self):
@@ -238,8 +247,7 @@
         for attendee in attendees:
             if self._isSelfAttendee(attendee):
                 if attendee.params[u'PARTSTAT'][0] == 'NEEDS-ACTION':
-                    # XXX Base this on something real
-                    delay = self.random.gauss(10, 2)
+                    delay = self.random.gauss(self._delay, self._spread)
                     self._accepting.add(href)
                     self._reactor.callLater(
                         delay, self._acceptInvitation, href, attendee)
@@ -332,12 +340,14 @@
 END:VEVENT
 END:VCALENDAR
 """))[0]
+    def setParameters(self, interval=25):
+        self._interval = interval
 
+
     def run(self):
         self._call = LoopingCall(self._addEvent)
         self._call.clock = self._reactor
-        # XXX Base this on something real
-        return self._call.start(25)
+        return self._call.start(self._interval)
 
 
     def _addEvent(self):

Modified: CalendarServer/trunk/contrib/performance/loadtest/sim.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/sim.py	2011-05-26 20:08:42 UTC (rev 7530)
+++ CalendarServer/trunk/contrib/performance/loadtest/sim.py	2011-05-26 20:13:40 UTC (rev 7531)
@@ -30,7 +30,7 @@
 from loadtest.ical import SnowLeopard
 from loadtest.profiles import Eventer, Inviter, Accepter
 from loadtest.population import (
-    Populator, ClientType, PopulationParameters, SmoothRampUp,
+    Populator, ProfileType, ClientType, PopulationParameters, SmoothRampUp,
     CalendarClientSimulator)
 
 
@@ -193,7 +193,9 @@
                     clientConfig["weight"],
                     ClientType(
                         namedAny(clientConfig["software"]),
-                        [namedAny(profile)
+                        [ProfileType(
+                                namedAny(profile["class"]),
+                                profile["params"])
                          for profile in clientConfig["profiles"]]))
         if not parameters.clients:
             parameters.addClient(

Modified: CalendarServer/trunk/contrib/performance/loadtest/test_sim.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_sim.py	2011-05-26 20:08:42 UTC (rev 7530)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_sim.py	2011-05-26 20:13:40 UTC (rev 7531)
@@ -34,7 +34,7 @@
 from loadtest.profiles import Eventer, Inviter, Accepter
 from loadtest.population import (
     SmoothRampUp, ClientType, PopulationParameters, Populator, CalendarClientSimulator,
-    SimpleStatistics)
+    ProfileType, SimpleStatistics)
 from loadtest.sim import (
     Server, Arrival, SimOptions, LoadSimulator, LagTrackingReactor, main)
 
@@ -302,12 +302,13 @@
         config.setContent(writePlistToString({
                     "clients": [{
                             "software": "loadtest.ical.SnowLeopard",
-                            "profiles": ["loadtest.profiles.Eventer"],
+                            "profiles": [{"class": "loadtest.profiles.Eventer", "params": {"interval": 25}}],
                             "weight": 3,
                             }]}))
         sim = LoadSimulator.fromCommandLine(['--config', config.path])
         expectedParameters = PopulationParameters()
-        expectedParameters.addClient(3, ClientType(SnowLeopard, [Eventer]))
+        expectedParameters.addClient(
+            3, ClientType(SnowLeopard, [ProfileType(Eventer, {"interval": 25})]))
         self.assertEquals(sim.parameters, expectedParameters)
 
         

Modified: CalendarServer/trunk/contrib/performance/run.sh
===================================================================
--- CalendarServer/trunk/contrib/performance/run.sh	2011-05-26 20:08:42 UTC (rev 7530)
+++ CalendarServer/trunk/contrib/performance/run.sh	2011-05-26 20:13:40 UTC (rev 7531)
@@ -20,6 +20,6 @@
 source support/shell.sh
 popd
 
-export PYTHONPATH=$PYTHONPATH:~/Projects/CalDAVClientLibrary/trunk/src
+export PYTHONPATH=$PYTHONPATH:~/Projects/CalendarServer/CalDAVClientLibrary/src
 
 exec "$@"

Modified: CalendarServer/trunk/contrib/performance/stats.py
===================================================================
--- CalendarServer/trunk/contrib/performance/stats.py	2011-05-26 20:08:42 UTC (rev 7530)
+++ CalendarServer/trunk/contrib/performance/stats.py	2011-05-26 20:13:40 UTC (rev 7531)
@@ -200,3 +200,13 @@
 
     def summarize(self, samples):
         return _Statistic.summarize(self, self.squash(samples))
+
+
+def quantize(data):
+    """
+    Given some continuous data, quantize it into appropriately sized
+    discrete buckets (eg, as would be suitable for constructing a
+    histogram of the values).
+    """
+    buckets = {}
+    return []

Modified: CalendarServer/trunk/contrib/performance/test_stats.py
===================================================================
--- CalendarServer/trunk/contrib/performance/test_stats.py	2011-05-26 20:08:42 UTC (rev 7530)
+++ CalendarServer/trunk/contrib/performance/test_stats.py	2011-05-26 20:13:40 UTC (rev 7531)
@@ -16,7 +16,7 @@
 
 from unittest import TestCase
 
-from stats import SQLDuration
+from stats import SQLDuration, quantize
 
 class SQLDurationTests(TestCase):
     def setUp(self):
@@ -40,3 +40,40 @@
             self.stat.normalize('SELECT foo FROM bar WHERE True'),
             'SELECT foo FROM bar WHERE ?')
 
+
+class QuantizationTests(TestCase):
+    """
+    Tests for L{quantize} which constructs discrete datasets of
+    dynamic quantization from continuous datasets.
+    """
+    def test_one(self):
+        """
+        A single data point is put into a bucket equal to its value and returned.
+        """
+        dataset = [5.0]
+        expected = [(5.0, [5.0])]
+        self.assertEqual(quantize(dataset), expected)
+
+
+    def test_two(self):
+        """
+        Each of two values are put into buckets the size of the
+        standard deviation of the sample.
+        """
+        dataset = [2.0, 5.0]
+        expected = [(1.5, [2.0]), (4.5, [5.0])]
+        self.assertEqual(quantize(dataset), expected)
+
+
+    def xtest_three(self):
+        """
+        If two out of three values fall within one bucket defined by
+        the standard deviation of the sample, that bucket is split in
+        half so each bucket has one value.
+        """
+
+
+    def xtest_alpha(self):
+        """
+        This exercises one simple case of L{quantize} with a small amount of data.
+        """

Modified: CalendarServer/trunk/contrib/performance/todo
===================================================================
--- CalendarServer/trunk/contrib/performance/todo	2011-05-26 20:08:42 UTC (rev 7530)
+++ CalendarServer/trunk/contrib/performance/todo	2011-05-26 20:13:40 UTC (rev 7531)
@@ -1,4 +1,34 @@
-description of each benchmark on the website
-investigate the performance regression near r6270 to see if it is real
-benchmarks for larger calendars (more events)
-extend report to know about linear scaling, quadratic scaling, etc perhaps
+Client profiles
+  - SnowLeopard iCal profile
+    - XMPP/push
+    - Delete from inbox
+    - Resync?
+    - Separate init behavior from normal operational behavior
+
+  - iPhone iCal profile
+    - Everything
+
+  - Lion iCal profile
+    - Everything
+
+Behavior models
+  - Allow configuration of
+    - Event creation
+    - Invitations
+    - Accept invitation
+
+Measurements/Reporting
+  - Collect aggregate task stats
+    - periodic poll
+    - event
+    - invite
+    - startup
+    - day zero?  resync?  pollb?  eventb?  startupb?  resyncb?
+      - still need to figure out what these are/mean
+  - QoS reports
+    - configurable pass/fail levels
+
+Server initialization
+  - Accounts
+    - DirectoryService?  LDAP?
+  - 
\ No newline at end of file
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110526/b874e8c0/attachment-0001.html>


More information about the calendarserver-changes mailing list