{"id":10821,"date":"2005-10-24T09:33:00","date_gmt":"2005-10-24T09:33:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/bharry\/2005\/10\/24\/how-many-users-will-your-team-foundation-server-support\/"},"modified":"2018-08-14T00:35:09","modified_gmt":"2018-08-14T00:35:09","slug":"how-many-users-will-your-team-foundation-server-support","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/bharry\/how-many-users-will-your-team-foundation-server-support\/","title":{"rendered":"How many users will your Team Foundation Server support?"},"content":{"rendered":"<p><font face=\"Arial\" size=\"2\">The information on server sizing in this blog post is no longer up to date.&nbsp; This was very early guidance before we had done many measurements.&nbsp; See <a href=\"http:\/\/blogs.msdn.com\/bharry\/archive\/2006\/01\/04\/509314.aspx\">http:\/\/blogs.msdn.com\/bharry\/archive\/2006\/01\/04\/509314.aspx<\/a>&nbsp;and later posts on my blog for more up to date information on our recommendations.<\/font>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-\n<font face=\"Arial\" size=\"2\">We&#8217;re deep into our load testing and server sizing efforts and I thought I&#8217;d share with everyone what we are doing and how we are thinking about it.<\/font>\n<font face=\"Arial\" size=\"2\">How big of a server do I need to support my team?&nbsp; Should I use a &#8220;single server&#8221; or separate Application tier and Data tier configuration?&nbsp; If I double the size of my team, will I need to increase the capacity of my server?&nbsp; We&#8217;ll provide high level guidelines for a mapping from team size to server configuration but if you want to understand how we do it and replicate it yourself, I&#8217;ll describe it for you.<\/font>\n<font face=\"Arial\" size=\"2\">To date, we&#8217;ve been very conservative on our server size recommendations.&nbsp; Officially our recommendations are as follows (they may have changed slightly from this but they are close).&nbsp; I think we&#8217;ve blogged this before but our dogfood server configuration is 2 server &#8211; 2P 2.?Ghz 4GB AT and a 4P 2.?Ghz 16GB DT and serves about 400 people.&nbsp; You&#8217;ll note our memory config is larger than what is recommended below.<\/font>\n<font face=\"Arial\" size=\"2\"><u>Configuration&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tiers&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Memory<br \/><\/u>One server, less than 20 users.&nbsp; Application and data tier server&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;single processor, 2.2 GHz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8 GB&nbsp;&nbsp;&nbsp;&nbsp; 1 GB<br \/>One server; 20 to 100 users.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Application and data tier server&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dual processors, 2.2 GHz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 30 GB&nbsp;&nbsp;&nbsp;&nbsp;2 GB<br \/>Two servers; 100 to 250 users.&nbsp;&nbsp; Application tier server&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;single processor, 2.2 GHz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;20 GB&nbsp;&nbsp;&nbsp;&nbsp;1 GB<br \/>Two servers; 100 to 250 users.&nbsp;&nbsp; Data tier server&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dual processors, 2.2 GHz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 80 GB&nbsp;&nbsp;&nbsp;&nbsp;2 GB<br \/>Two servers; 250 to 500 users.&nbsp;&nbsp; Application tier server&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dual processors, 2.2 GHz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;40 GB&nbsp;&nbsp;&nbsp;&nbsp;2 GB<br \/>Two Servers; 250 to 500 users.&nbsp;&nbsp; Data tier server&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quadruple processors, 2.2 GHz &nbsp;150 GB&nbsp; 4 GB<\/font>\n<font face=\"Arial\" size=\"2\">Once we have finished our load testing, I expect we will update the configurations above some.&nbsp; Based on what I&#8217;ve seen so far, we will be increasing the supported team sizes.<\/font>\n<font face=\"Arial\" size=\"2\"><font size=\"3\"><strong>Approach to load testing<br \/><\/strong><\/font>The first question to answer is &#8220;how much load does a &#8220;typical&#8221; user put on the system?&#8221;&nbsp; We&#8217;ve gathered this information by monitoring usage of our dogfood server for months.&nbsp; Of course this can vary by team based on the sizes of the projects they work on, their development methodologies and the number and type of automated tools that they have.&nbsp; For now we are making the assumption that, to a first approximation, the usage we see on our dogfood server is representative of what other people will see.&nbsp; We are currently in the process of comparing our load to what other teams at Microsoft experience to do a little more validation of that assumption.&nbsp; It is possible for you to collect this data for your own team and here&#8217;s how&#8230;<\/font>\n<font face=\"Arial\" size=\"2\">Team Foundation Server has a feature to log every server &#8220;command&#8221; (a command is a TFS web service call) to a database on the data tier.&nbsp; The database is called TFSActivityLogging.&nbsp; Each row records what the request was, when it happened, how long it took, who did it, from what IP address, and more.&nbsp; This information is tracked in a rolling 7 day window &#8211; there&#8217;s a nightly SQL job that deletes data over 7 days old.&nbsp; We have taken snapshots of this data over the past few months and done some processing on it to determine what the typical &#8220;peak&#8221; load on the server is.&nbsp; To do this we aggregated the commands into 10 minute windows and divided by 600 (# of seconds in a 10 minute window) to give the number of &#8220;commands\/sec&#8221; in 10 minute chunks.&nbsp; We then graphed these 10 minute windows over a 24 hour day to see what the load profile throughout a day looks like.&nbsp; Based on that we can easily see what the peak &#8220;commands\/sec&#8221; is (in 10 minute windows).&nbsp; For our dogfood server this came out to be about 35 commands\/sec. You can then take this number and divide by the number of users using the server &#8211; 35 peak commands\/sec \/ 350 team users = 0.1 peak commands\/sec\/user.&nbsp; This tells you how many peak commands\/sec each member of your team contributes &#8211; and 0.1 is what we have computed for our dogfood server (and are currently validating that it is consistent with other teams).&nbsp; To enable command logging you&rsquo;ll need to edit the setting for CommandLogging in the top level TFS web.config.<\/font>\n<font face=\"Arial\" size=\"2\">An important note &#8211; As I said, the TFSActivityLogging database includes all commands executed against the server.&nbsp; This not only includes requests made from clients but also includes requests made from one service to another on the server itself.&nbsp; For example, if you call the Version Control service, it may call the security service to do a permission check.&nbsp; Both are recorded.&nbsp; However, when computing the peak commands\/sec\/user above, you need to exclude the service to service requests because you only want to look at direct client generated requests.&nbsp; This will be important in how we craft the load testing below.&nbsp; You can ignore these easily because the rows in the TFSActivityLogging database include a &#8220;UserAgent&#8221; &#8211; what application was used to make the request.&nbsp; All service to service have the user agent set such that &#8220;w3wp.exe&#8221; will appear in the string.&nbsp; You need to exclude these before you do the 10 minute aggregations.<\/font>\n<font face=\"Arial\" size=\"2\">Now you know how to compute the peak commands\/sec\/user (0.1 for our server).&nbsp; How do you use this to answer the questions above?&nbsp; Well, let&#8217;s say I want to grow my team from 50 people to 100 people on the same server.&nbsp; Will my server handle it?&nbsp; To handle it, the server will need to support 0.1 * 100 == 10 commands\/sec peak.<\/font>\n<font face=\"Arial\" size=\"2\">To measure how much load a server can take, we&#8217;ve written a set of load tests for the Team System load testing tool.&nbsp; We can then run these load tests with a ramp load (increasing tests\/sec) against different hardware configurations and different data set sizes to see how many commands\/sec we can get and what the corresponding response times are.&nbsp; We can measure the test\/sec from the load test agents to determine how many commands per second we are generating.&nbsp; Unfortunately this also requires a bit of calculating to get it exactly right.&nbsp; There isn&#8217;t a 1-1 correspondence between tests\/second and commands per second &#8211; because some tests execute multiple commands.&nbsp; To account for this, we run the load tests for a while, compute the number of commands (excluding server to server ones) and divide that by the number of tests that the load test ran.&nbsp; This gives a ratio of commands\/sec to tests\/sec.<\/font>\n<font face=\"Arial\" size=\"2\">Two other important issues remain with the load tests.&nbsp; First, you need to determine what the appropriate &#8220;mix&#8221; of commands to simulate is.&nbsp; To do this, we&#8217;ve gone back to the command log on our dogfood database.&nbsp; We run a query that aggregates the counts of each command and gives a percentage of all commands.&nbsp; It turns out that relatively few commands make up the vast majority of that load.&nbsp; As a result we&#8217;ve actually only written load tests for about 30-40 of the 130 or so possible commands because the sum total of all of the others don&#8217;t account for more than a 1% of all commands executed against our dogfood server.&nbsp; Using this data, we created a load test mix that approximates the load distribution we see on the dog food server.<\/font>\n<font face=\"Arial\" size=\"2\">Here&#8217;s the dogfood distribution we are basing the load tests on.&nbsp; This includes all web methods with more than 0.1% of the total execution time.&nbsp; Note, we are still doing some perf work so I expect this to change some over time.<\/font>\n<font face=\"Courier New\" size=\"2\"><u>Service&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Web method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Execution Time (s)&nbsp;&nbsp;# of calls&nbsp;&nbsp;&nbsp;% Execution Time<br \/><\/u>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Download&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;83528.15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2494408&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;24.51%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UpdateLocalVersion&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;68361.83&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;25179&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 20.06%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PendChanges&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;53533.50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2834&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 15.71%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;42588.98&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;17913&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12.50%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QueryPendingSets&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;19670.23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14065&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5.77%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QueryItemsExtended&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;11612.75&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7974&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.41%<br \/>WorkItem Tracking&nbsp;&nbsp;&nbsp;QueryWorkitemCount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8007.08&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;126827&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.35%<br \/>WorkItem Tracking&nbsp;&nbsp;&nbsp;QueryWorkitems&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6563.08&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;88849&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.93%<br \/>WorkItem Tracking&nbsp;&nbsp;&nbsp;PageWorkitemsByIds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6388.91&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;41729&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.87%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UndoPendingChanges&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6345.44&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.86%<br \/>WorkItem Tracking&nbsp;&nbsp;&nbsp;Update&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5991.57&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6488&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.76%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Unshelve&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2382.38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;373&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.70%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QueryHistory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2209.30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6228&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.65%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Resolve&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2009.92&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1845&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.59%<br \/>WorkItem Tracking&nbsp;&nbsp;&nbsp;GetWorkItem&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1991.33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;46362&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.58%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QueryItemsById&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1717.28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;88816&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.50%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QueryItems&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1660.01&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;18974&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.49%<br \/>WorkItem Tracking&nbsp;&nbsp;&nbsp;GetMetadata&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1650.80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9244&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.48%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FilterPaths&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1463.33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10597&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.43%<br \/>Integration&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IsMember&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1412.33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;289420&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.41%<br \/>WorkItem Tracking&nbsp;&nbsp;&nbsp;PageWorkitemsByIdRevs&nbsp; 1158.99&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1537&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.34%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Checkin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1128.93&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;498&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.33%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Upload&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1048.00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8096&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.31%<br \/>WorkItem Tracking&nbsp;&nbsp; GetStoredQueries&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1038.85&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;17445&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.30%<br \/>WorkItem Tracking&nbsp;&nbsp; PageItemsOnBehalfOf&nbsp;&nbsp;&nbsp;&nbsp;609.14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4194&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.18%<br \/>Integration&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetRegistrationEntries&nbsp;564.51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6833&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.17%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QueryShelvesets&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;561.55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1365&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.16%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QueryWorkspaces&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;491.65&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4748&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.14%<br \/>Integration&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ListProjects&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;395.92&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4286&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.12%<br \/>Version Control&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QueryChangeset&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;382.45&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3916&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.11%<br \/>TFS Build&nbsp;&nbsp;&nbsp;&nbsp;&amp;n\nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StartBuild&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;357.30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.10%<\/font>\n<font face=\"Arial\" size=\"2\">Second, you need to think about how much data is on the server you are testing.&nbsp; This can have a huge impact on your results.&nbsp; Running against a small database can yield extremely high rps (requests per second) because all of the data is kept in memory.&nbsp; A much larger database might support 2, 3 or 4 times fewer rps.&nbsp; To be able to experiment with different sizes of data, we created a tool we call &#8220;dbfiller&#8221;.&nbsp; You tell it how many Team Projects, Files, Work items, attachments, &#8230; that you want and it creates a database with that data in it (a really large database might take a day or two to create).&nbsp; Another approach is to take a backup of your production database and restore it onto a test server to run load tests against.&nbsp; You wouldn&#8217;t want to run the load tests against a production server as the load tests simulate many commands (including creating, modifying and deleting work items, files, etc).<\/font>\n<font face=\"Arial\" size=\"2\">When we run the load test, we run it with a step load, stepping 1 user every 30 minutes and we run it for 8 hours.&nbsp; Note that the number of &#8220;users&#8221; in the load test has no real correspondence to the number of people we are simulating.&nbsp; Each &#8220;user&#8221; in the load test ramp represents 1 thread in the load test engine running requests back to back as fast as it possibly can.&nbsp; We are using the calculations above to determine how many people we can support.&nbsp; The load test &#8220;users&#8221; are just a way to gradually increase the load on the server.&nbsp; The actual count is not important.<\/font>\n<font face=\"Arial\" size=\"2\">While it runs, we collect perf counters, including tests\/sec, CPU utilization, disk queue length, available memory, etc.&nbsp; We also collect response times for the tests.&nbsp; In determining when the server has reached the most load it can service we look at a couple of things.&nbsp; First we look at CPU utilization.&nbsp; Remember what we&#8217;re measuring against here is &#8220;peak&#8221; load so we run the CPU fairly hot.&nbsp; That said, I&#8217;d say once the server hits 80-85% utilization you&#8217;re done.&nbsp; You definitely don&#8217;t want to run your server past that (even at peak times) and if you plan on seeing growth on your server, I&#8217;d not want to run it past 50-60% peak utilization.&nbsp; Second we look at response times of the tests.&nbsp; The main thing we are looking for here is &#8220;the knee in the curve&#8221;.&nbsp; The response time is how long a user will be waiting for that command to complete.&nbsp; You want to make sure that the times are &#8220;reasonable&#8221; and below any &#8220;knee&#8221;.&nbsp; The &#8220;knee&#8221; is the point in the curve where small increases in load start yielding disproportionately larger increases in the response time.&nbsp; When this happens your server is too busy.<\/font>\n<br \/><font face=\"Arial\"><strong>Putting it all together<\/strong><\/font>\n<font face=\"Arial\" size=\"2\">A few weeks ago we did our first full load test run using this methodology.&nbsp; We used the numbers I&#8217;ve quoted above and in addition to that we used:<\/font>\n<font face=\"Arial\" size=\"2\"><u>Hardware<br \/><\/u>Single server install configuration<br \/>Dual Processor, 3.4GHz, 4GB ram, SATA drive<\/font>\n<font face=\"Arial\" size=\"2\"><u>Data size (the most interesting subset of information)<br \/><\/u>36 Team Projects<br \/>35,000 files<br \/>21,000 change sets<br \/>80 workspaces<br \/>2,000 shelvesets<br \/>27,750 work items<br \/>194,250 work item revisions<br \/>2,000 work item queries<br \/>500 builds<br \/>Note, the database grows as the load test runs be cause part of what the load tests do is create new work items, add new files, etc.<\/font>\n<font face=\"Arial\" size=\"2\"><u>Results<br \/><\/u>We achieved&nbsp;13.6 tests\/sec at 50% cpu utilization and&nbsp;20.4 tests\/sec at about 80% cpu utilization.&nbsp; The response times were more linear than we predicted.&nbsp; I don&#8217;t think we ran the tests to high enough load to see the knee (we certainly didn&#8217;t see it up to 85% cpu utilization).&nbsp; We&#8217;re investigating this a bit more because you certainly should see it at some point.<\/font>\n<font face=\"Arial\" size=\"2\">Using the math above, this server configuration can support a team of: 20.4 tests\/sec * 5.19 commands\/test \/ 0.1 peak commands\/sec\/user = 1060 users.<\/font>\n<font face=\"Arial\" size=\"2\">That&#8217;s the absolute peak.&nbsp; In sizing a server for my team, I&#8217;d use the 50% cpu utilization number resulting in: 13.6 tests\/sec * 5.19 commands\/test \/ 0.1 peak commands\/sec\/user = 706 users.<\/font>\n<font face=\"Arial\" size=\"2\">Now, the truth is that a team of 706 people would actually have more data than we used to populate the database (we based these numbers on a 100-200 person team) so it wouldn&#8217;t actually support a team of that size &#8211; the additional data size would cause some slow down.&nbsp; However, it tells you that if this is your data set size, you&rsquo;re covered for a pretty darn long way.<\/font>\n<font face=\"Arial\" size=\"2\">I hope this analysis was interesting and helpful.&nbsp; Sorry for writing so much but it&#8217;s a pretty involved topic.&nbsp; I&#8217;ll try to find some shorter things to write about.&nbsp; If there is interest, we can look at posting our load tests, dbfiller and other tools that we used for customers to use in their own capacity planning exercises.&nbsp; As I said before, we&#8217;ll be running this over a variety of configurations and creating an updated tabular table like the one at the top for people who don&#8217;t want to invest a week in crafting their own custom load test configuration.<\/font>\n<font face=\"Arial\" size=\"2\">Thanks,<\/font>\n<font face=\"Arial\" size=\"2\">Brian<\/font><\/p>\n<p><font face=\"Arial\"><\/font>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The information on server sizing in this blog post is no longer up to date.&nbsp; This was very early guidance before we had done many measurements.&nbsp; See http:\/\/blogs.msdn.com\/bharry\/archive\/2006\/01\/04\/509314.aspx&nbsp;and later posts on my blog for more up to date information on our recommendations. &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- We&#8217;re deep into our load testing and server sizing efforts and I [&hellip;]<\/p>\n","protected":false},"author":244,"featured_media":14617,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-10821","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"blog_post_summary":"<p>The information on server sizing in this blog post is no longer up to date.&nbsp; This was very early guidance before we had done many measurements.&nbsp; See http:\/\/blogs.msdn.com\/bharry\/archive\/2006\/01\/04\/509314.aspx&nbsp;and later posts on my blog for more up to date information on our recommendations. &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- We&#8217;re deep into our load testing and server sizing efforts and I [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/posts\/10821","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/users\/244"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/comments?post=10821"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/posts\/10821\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/media\/14617"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/media?parent=10821"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/categories?post=10821"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/bharry\/wp-json\/wp\/v2\/tags?post=10821"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}