<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[15106] CalendarServer/branches/users/sredmond/clientsim/doc/Admin/LoadSimulation.rst</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/15106">15106</a></dd>
<dt>Author</dt> <dd>sredmond@apple.com</dd>
<dt>Date</dt> <dd>2015-09-04 13:36:23 -0700 (Fri, 04 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Updates admin docs</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssredmondclientsimdocAdminLoadSimulationrst">CalendarServer/branches/users/sredmond/clientsim/doc/Admin/LoadSimulation.rst</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserssredmondclientsimdocAdminLoadSimulationrst"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sredmond/clientsim/doc/Admin/LoadSimulation.rst (15105 => 15106)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sredmond/clientsim/doc/Admin/LoadSimulation.rst        2015-09-04 18:36:20 UTC (rev 15105)
+++ CalendarServer/branches/users/sredmond/clientsim/doc/Admin/LoadSimulation.rst        2015-09-04 20:36:23 UTC (rev 15106)
</span><span class="lines">@@ -117,7 +117,8 @@
</span><span class="cx"> 
</span><span class="cx"> The client sim's default configuration file is found here::
</span><span class="cx"> 
</span><del>- contrib/performance/loadtest/config.plist
</del><ins>+ .. contrib/performance/loadtest/config.plist
+ contrib.performance.loadtest.settings.config
</ins><span class="cx"> 
</span><span class="cx"> The config file defines
</span><span class="cx"> 
</span><span class="lines">@@ -131,9 +132,10 @@
</span><span class="cx"> 
</span><span class="cx"> Specify the URI to which the client sim should connect, e.g::
</span><span class="cx"> 
</span><del>-                &lt;!-- Identify the server to be load tested. --&gt;
-                &lt;key&gt;server&lt;/key&gt;
-                &lt;string&gt;https://127.0.0.1:8443/&lt;/string&gt;
</del><ins>+    &quot;server&quot;: &quot;https://127.0.0.1:8443&quot;
+                .. &lt;!-- Identify the server to be load tested. --&gt;
+                .. &lt;key&gt;server&lt;/key&gt;
+                .. &lt;string&gt;https://127.0.0.1:8443/&lt;/string&gt;
</ins><span class="cx"> 
</span><span class="cx"> User Accounts
</span><span class="cx"> -------------
</span><span class="lines">@@ -141,29 +143,30 @@
</span><span class="cx"> User accounts are defined in the 'accounts' key of the plist:
</span><span class="cx"> 
</span><span class="cx"> ::
</span><ins>+    &quot;accounts&quot;: recordsFromCSVFile(&quot;contrib/performance/loadtest/accounts.csv&quot;)
</ins><span class="cx"> 
</span><del>-                &lt;!-- Define the credentials of the clients which will be used to load test 
-                        the server. These credentials must already be valid on the server. --&gt;
-                &lt;key&gt;accounts&lt;/key&gt;
-                &lt;dict&gt;
-                        &lt;!-- The loader is the fully-qualified Python name of a callable which 
-                                returns a list of directory service records defining all of the client accounts 
-                                to use. contrib.performance.loadtest.sim.recordsFromCSVFile reads username, 
-                                password, mailto triples from a CSV file and returns them as a list of faked 
-                                directory service records. --&gt;
-                        &lt;key&gt;loader&lt;/key&gt;
-                        &lt;string&gt;contrib.performance.loadtest.sim.recordsFromCSVFile&lt;/string&gt;
</del><ins>+                .. &lt;!-- Define the credentials of the clients which will be used to load test 
+                ..         the server. These credentials must already be valid on the server. --&gt;
+                .. &lt;key&gt;accounts&lt;/key&gt;
+                .. &lt;dict&gt;
+                ..         &lt;!-- The loader is the fully-qualified Python name of a callable which 
+                ..                 returns a list of directory service records defining all of the client accounts 
+                ..                 to use. contrib.performance.loadtest.sim.recordsFromCSVFile reads username, 
+                ..                 password, mailto triples from a CSV file and returns them as a list of faked 
+                ..                 directory service records. --&gt;
+                ..         &lt;key&gt;loader&lt;/key&gt;
+                ..         &lt;string&gt;contrib.performance.loadtest.sim.recordsFromCSVFile&lt;/string&gt;
</ins><span class="cx"> 
</span><del>-                        &lt;!-- Keyword arguments may be passed to the loader. --&gt;
-                        &lt;key&gt;params&lt;/key&gt;
-                        &lt;dict&gt;
-                                &lt;!-- recordsFromCSVFile interprets the path relative to the config.plist, 
-                                        to make it independent of the script's working directory while still allowing 
-                                        a relative path. This isn't a great solution. --&gt;
-                                &lt;key&gt;path&lt;/key&gt;
-                                &lt;string&gt;contrib/performance/loadtest/accounts.csv&lt;/string&gt;
-                        &lt;/dict&gt;
-                &lt;/dict&gt;
</del><ins>+                ..         &lt;!-- Keyword arguments may be passed to the loader. --&gt;
+                ..         &lt;key&gt;params&lt;/key&gt;
+                ..         &lt;dict&gt;
+                ..                 &lt;!-- recordsFromCSVFile interprets the path relative to the config.plist, 
+                ..                         to make it independent of the script's working directory while still allowing 
+                ..                         a relative path. This isn't a great solution. --&gt;
+                ..                 &lt;key&gt;path&lt;/key&gt;
+                ..                 &lt;string&gt;contrib/performance/loadtest/accounts.csv&lt;/string&gt;
+                ..         &lt;/dict&gt;
+                .. &lt;/dict&gt;
</ins><span class="cx"> 
</span><span class="cx"> The accounts.csv file has lines like shown below::
</span><span class="cx"> 
</span><span class="lines">@@ -174,37 +177,43 @@
</span><span class="cx"> 
</span><span class="cx"> This section configures the number of accounts to use, and defines how quickly clients are initialized when the sim starts::
</span><span class="cx"> 
</span><del>-                &lt;!-- Define how many clients will participate in the load test and how 
-                        they will show up. --&gt;
-                &lt;key&gt;arrival&lt;/key&gt;
-                &lt;dict&gt;
</del><ins>+    &quot;arrival&quot;: SmoothRampUp(
+        groups=2,
+        groupSize=1,
+        interval=3,
+        clientsPerUser=1
+    )
+                .. &lt;!-- Define how many clients will participate in the load test and how 
+                ..         they will show up. --&gt;
+                .. &lt;key&gt;arrival&lt;/key&gt;
+                .. &lt;dict&gt;
</ins><span class="cx"> 
</span><del>-                        &lt;!-- Specify a class which creates new clients and introduces them into 
-                                the test. contrib.performance.loadtest.population.SmoothRampUp introduces 
-                                groups of new clients at fixed intervals up to a maximum. The size of the 
-                                group, interval, and maximum are configured by the parameters below. The 
-                                total number of clients is groups * groupSize, which needs to be no larger 
-                                than the number of credentials created in the accounts section. --&gt;
-                        &lt;key&gt;factory&lt;/key&gt;
-                        &lt;string&gt;contrib.performance.loadtest.population.SmoothRampUp&lt;/string&gt;
</del><ins>+                ..         &lt;!-- Specify a class which creates new clients and introduces them into 
+                ..                 the test. contrib.performance.loadtest.population.SmoothRampUp introduces 
+                ..                 groups of new clients at fixed intervals up to a maximum. The size of the 
+                ..                 group, interval, and maximum are configured by the parameters below. The 
+                ..                 total number of clients is groups * groupSize, which needs to be no larger 
+                ..                 than the number of credentials created in the accounts section. --&gt;
+                ..         &lt;key&gt;factory&lt;/key&gt;
+                ..         &lt;string&gt;contrib.performance.loadtest.population.SmoothRampUp&lt;/string&gt;
</ins><span class="cx"> 
</span><del>-                        &lt;key&gt;params&lt;/key&gt;
-                        &lt;dict&gt;
-                                &lt;!-- groups gives the total number of groups of clients to introduce. --&gt;
-                                &lt;key&gt;groups&lt;/key&gt;
-                                &lt;integer&gt;20&lt;/integer&gt;
</del><ins>+                ..         &lt;key&gt;params&lt;/key&gt;
+                ..         &lt;dict&gt;
+                ..                 &lt;!-- groups gives the total number of groups of clients to introduce. --&gt;
+                ..                 &lt;key&gt;groups&lt;/key&gt;
+                ..                 &lt;integer&gt;20&lt;/integer&gt;
</ins><span class="cx"> 
</span><del>-                                &lt;!-- groupSize is the number of clients in each group of clients. It's 
-                                        really only a &quot;smooth&quot; ramp up if this is pretty small. --&gt;
-                                &lt;key&gt;groupSize&lt;/key&gt;
-                                &lt;integer&gt;1&lt;/integer&gt;
</del><ins>+                ..                 &lt;!-- groupSize is the number of clients in each group of clients. It's 
+                ..                         really only a &quot;smooth&quot; ramp up if this is pretty small. --&gt;
+                ..                 &lt;key&gt;groupSize&lt;/key&gt;
+                ..                 &lt;integer&gt;1&lt;/integer&gt;
</ins><span class="cx"> 
</span><del>-                                &lt;!-- Number of seconds between the introduction of each group. --&gt;
-                                &lt;key&gt;interval&lt;/key&gt;
-                                &lt;integer&gt;3&lt;/integer&gt;
-                        &lt;/dict&gt;
</del><ins>+                ..                 &lt;!-- Number of seconds between the introduction of each group. --&gt;
+                ..                 &lt;key&gt;interval&lt;/key&gt;
+                ..                 &lt;integer&gt;3&lt;/integer&gt;
+                ..         &lt;/dict&gt;
</ins><span class="cx"> 
</span><del>-                &lt;/dict&gt;
</del><ins>+                .. &lt;/dict&gt;
</ins><span class="cx"> 
</span><span class="cx"> In the default configuration, one client is initialized every 3 seconds, until 20 clients are initialized. As soon as a client is initialized, it begins to perform its specified behaviors at the configured rates (see &quot;Client Behaviors&quot;).
</span><span class="cx"> 
</span><span class="lines">@@ -223,67 +232,83 @@
</span><span class="cx"> 
</span><span class="cx"> ::
</span><span class="cx"> 
</span><del>- &lt;key&gt;software&lt;/key&gt;
- &lt;string&gt;contrib.performance.loadtest.ical.SnowLeopard&lt;/string&gt;
</del><ins>+    &quot;software&quot;: OS_X_10_11
</ins><span class="cx"> 
</span><ins>+ .. &lt;key&gt;software&lt;/key&gt;
+ .. &lt;string&gt;contrib.performance.loadtest.ical.SnowLeopard&lt;/string&gt;
+
</ins><span class="cx"> - 'params', optionally specifying parameters accepted by this software. For example:
</span><span class="cx"> 
</span><span class="cx"> ::
</span><ins>+    
+    &quot;params&quot;: {
+        &quot;title&quot;: &quot;10.11&quot;,
+        &quot;calendarHomePollInterval&quot;: 5,
+        &quot;supportAmpPush&quot;: True,
+        &quot;ampPushHost&quot;: &quot;localhost&quot;,
+        &quot;ampPushPort&quot;: 62311
+    },
</ins><span class="cx"> 
</span><del>-  &lt;!-- Arguments to use to initialize the SnowLeopard instance. --&gt;
-  &lt;key&gt;params&lt;/key&gt;
-  &lt;dict&gt;
-          &lt;!-- SnowLeopard can poll the calendar home at some interval. This is 
-                  in seconds. --&gt;
-          &lt;key&gt;calendarHomePollInterval&lt;/key&gt;
-          &lt;integer&gt;30&lt;/integer&gt;
</del><ins>+  .. &lt;!-- Arguments to use to initialize the SnowLeopard instance. --&gt;
+  .. &lt;key&gt;params&lt;/key&gt;
+  .. &lt;dict&gt;
+  ..         &lt;!-- SnowLeopard can poll the calendar home at some interval. This is 
+  ..                 in seconds. --&gt;
+  ..         &lt;key&gt;calendarHomePollInterval&lt;/key&gt;
+  ..         &lt;integer&gt;30&lt;/integer&gt;
</ins><span class="cx"> 
</span><del>-          &lt;!-- If the server advertises xmpp push, SnowLeopard can wait for notifications 
-                  about calendar home changes instead of polling for them periodically. If 
-                  this option is true, then look for the server advertisement for xmpp push 
-                  and use it if possible. Still fall back to polling if there is no xmpp push 
-                  advertised. --&gt;
-          &lt;key&gt;supportPush&lt;/key&gt;
-          &lt;false /&gt;
-  &lt;/dict&gt;
</del><ins>+  ..         &lt;!-- If the server advertises xmpp push, SnowLeopard can wait for notifications 
+  ..                 about calendar home changes instead of polling for them periodically. If 
+  ..                 this option is true, then look for the server advertisement for xmpp push 
+  ..                 and use it if possible. Still fall back to polling if there is no xmpp push 
+  ..                 advertised. --&gt;
+  ..         &lt;key&gt;supportPush&lt;/key&gt;
+  ..         &lt;false /&gt;
+  .. &lt;/dict&gt;
</ins><span class="cx"> 
</span><del>-- 'profiles' is an array of dictionaries specifying individual behaviors of this software. Each dict has a 'class' key which specifies the implementation class for this behavior, and a 'params' dict with options specific to that behavior. For example:
</del><ins>+- 'profiles' is an array of profiles specifying individual behaviors of this software.
</ins><span class="cx"> 
</span><span class="cx"> ::
</span><span class="cx"> 
</span><del>- &lt;!-- This profile accepts invitations to events, handles cancels, and
-      handles replies received. --&gt;
- &lt;dict&gt;
-         &lt;key&gt;class&lt;/key&gt;
-         &lt;string&gt;contrib.performance.loadtest.profiles.Accepter&lt;/string&gt;
</del><ins>+    Eventer(enabled=True, interval=0.1, eventStartDistribution=STANDARD_WORK_DISTRIBUTION),
+    Inviter(enabled=True, interval=1, numInviteesDistribution=NormalDistribution(7, 2)),
+    Tasker(enabled=False, interval=30),
+    Completer(enabled=True, interval=180, completeLikelihood=BernoulliDistribution(0.8)),
+    CalendarMaker(enabled=True, interval=10)
</ins><span class="cx"> 
</span><del>-         &lt;key&gt;params&lt;/key&gt;
-         &lt;dict&gt;
-                 &lt;key&gt;enabled&lt;/key&gt;
-                 &lt;true/&gt;
</del><ins>+ .. &lt;!-- This profile accepts invitations to events, handles cancels, and
+ ..      handles replies received. --&gt;
+ .. &lt;dict&gt;
+ ..         &lt;key&gt;class&lt;/key&gt;
+ ..         &lt;string&gt;contrib.performance.loadtest.profiles.Accepter&lt;/string&gt;
</ins><span class="cx"> 
</span><del>-                 &lt;!-- Define how long to wait after seeing a new invitation before 
-                         accepting it. --&gt;
-                 &lt;key&gt;acceptDelayDistribution&lt;/key&gt;
-                 &lt;dict&gt;
-                         &lt;key&gt;type&lt;/key&gt;
-                         &lt;string&gt;contrib.performance.stats.NormalDistribution&lt;/string&gt;
-                         &lt;key&gt;params&lt;/key&gt;
-                         &lt;dict&gt;
-                                 &lt;!-- mean --&gt;
-                                 &lt;key&gt;mu&lt;/key&gt;
-                                 &lt;integer&gt;60&lt;/integer&gt;
-                                 &lt;!-- standard deviation --&gt;
-                                 &lt;key&gt;sigma&lt;/key&gt;
-                                 &lt;integer&gt;60&lt;/integer&gt;
-                         &lt;/dict&gt;
-                 &lt;/dict&gt;
-         &lt;/dict&gt;
- &lt;/dict&gt;
</del><ins>+ ..         &lt;key&gt;params&lt;/key&gt;
+ ..         &lt;dict&gt;
+ ..                 &lt;key&gt;enabled&lt;/key&gt;
+ ..                 &lt;true/&gt;
</ins><span class="cx"> 
</span><ins>+ ..                 &lt;!-- Define how long to wait after seeing a new invitation before 
+ ..                         accepting it. --&gt;
+ ..                 &lt;key&gt;acceptDelayDistribution&lt;/key&gt;
+ ..                 &lt;dict&gt;
+ ..                         &lt;key&gt;type&lt;/key&gt;
+ ..                         &lt;string&gt;contrib.performance.stats.NormalDistribution&lt;/string&gt;
+ ..                         &lt;key&gt;params&lt;/key&gt;
+ ..                         &lt;dict&gt;
+ ..                                 &lt;!-- mean --&gt;
+ ..                                 &lt;key&gt;mu&lt;/key&gt;
+ ..                                 &lt;integer&gt;60&lt;/integer&gt;
+ ..                                 &lt;!-- standard deviation --&gt;
+ ..                                 &lt;key&gt;sigma&lt;/key&gt;
+ ..                                 &lt;integer&gt;60&lt;/integer&gt;
+ ..                         &lt;/dict&gt;
+ ..                 &lt;/dict&gt;
+ ..         &lt;/dict&gt;
+ .. &lt;/dict&gt;
+
</ins><span class="cx"> Some parameters may be safely modified to suit your purposes, for example you might choose to disable certain profiles (by setting 'enabled' to false) in order to simulate only specific types of activity. Also, you can edit the params for the various distributions to configure how often things happen.
</span><span class="cx"> 
</span><del>-Motivated readers may also develop new behaviors for existing clients, or even entirely new clients. An example of adding a new behavior to an existing client can be found here: http://trac.calendarserver.org/changeset/8428. As of this writing, we have only the one Snow Leopard client simulator, and would happily accept patches that implement additional clients!
</del><ins>+Motivated readers may also develop new behaviors for existing clients, or even entirely new clients. An example of adding a new behavior to an existing client can be found here: http://trac.calendarserver.org/changeset/8428.
</ins><span class="cx"> 
</span><span class="cx"> ---------------------
</span><span class="cx"> Scalability
</span><span class="lines">@@ -295,6 +320,10 @@
</span><span class="cx"> 
</span><span class="cx"> To use four instances on the local host::
</span><span class="cx"> 
</span><ins>+Python Configuration::
+workers=[&quot;./python contrib/performance/loadtest/ampsim.py&quot; * 4]  # Spawns for workers
+
+PList Configuration::
</ins><span class="cx">  &lt;key&gt;workers&lt;/key&gt;
</span><span class="cx">  &lt;array&gt;
</span><span class="cx">      &lt;string&gt;./python contrib/performance/loadtest/ampsim.py&lt;/string&gt;
</span></span></pre>
</div>
</div>

</body>
</html>