<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Basic Verbs &#187; Environment</title>
	<atom:link href="http://basicverbs.com/category/development/environment/feed/" rel="self" type="application/rss+xml" />
	<link>http://basicverbs.com</link>
	<description>Design AND Development Blog</description>
	<lastBuildDate>Fri, 19 Feb 2010 09:51:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Benchmark of django deployment techniques</title>
		<link>http://basicverbs.com/benchmark-of-django-deployment-techniques/</link>
		<comments>http://basicverbs.com/benchmark-of-django-deployment-techniques/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 19:55:02 +0000</pubDate>
		<dc:creator>Vasil</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Environment]]></category>
		<category><![CDATA[Server side]]></category>

		<guid isPermaLink="false">http://basicverbs.com/?p=63</guid>
		<description><![CDATA[I made a benchmark of different Django deployment techniques and configurations mostly for my personal purposes. The results are published in the hope that it would save others some time. The benchmark was not designed to test the speed of Django itself, only to give relative comparison between different techniques for running a Django application [...]]]></description>
			<content:encoded><![CDATA[<p>I made a benchmark of different Django deployment techniques and configurations mostly for my personal purposes. The results are published in the hope that it would save others some time. The benchmark was not designed to test the speed of Django itself, only to give relative comparison between different techniques for running a Django application in production environments. I&#8217;m not affiliated with any of the following open source projects: Apache,  Nginx, Cherokee, mod_wsgi, mod_python, Cherrypy or uWSGI. Further, I&#8217;m not claiming to be an expert in configuring any of the software mentioned here.</p>
<h2>What was measured</h2>
<p>The Django project used for the benchmark was a simple application for displaying rows from 3 different tables with pagination. Each page had references to 3 static files (css, javascript and an image). Each page involved rendering a simple template inheriting from a base template and including another one, built-in filters were also used. The database had more than a million records in all three tables combined. I browsed different pages of the application over a proxy which recorded the URLs of the browsing session. So for each request that was handled by the application there were 3 more requests for static files. For each deployment technique I ran 4 tests at different concurrency levels for 1 minute making GET requests to the recorded URLs. For each test run I recorded throughput (number of requests served per second), response time (average time in which a request was served) and longest request (the longest time a request was served in each run). Only for the tests at highest concurrency levels I recorded memory usage. I tried to make sure that only the necessary processes for each test were running at a time. Automatic maintenance tasks on the system and the database were turned off. Every test cycle was repeated at least 3 times to recheck the results.</p>
<h2>Hardware and software details</h2>
<p>For generating the loads I used Siege and ran all the benchmarks over gigabit ethernet from a 2.16 GHz machine with 2 GB of RAM running OS X Snow Leopard.</p>
<p>The system that served as a web and database server ran in a VMware appliance on a 2.8 GHz Core2Duo PC with 8GBs of RAM. The appliance was given only 1GB of working memory and assigned both cores of the CPU. Software details:</p>
<ul>
<li>Ubuntu 9.10 32b</li>
<li>Python 2.6</li>
<li>PostgreSQL 8.4</li>
<li>Apache 2.2.12 worker MPM</li>
<li>Nginx 0.7.64</li>
<li>Cherokee 0.99.39</li>
<li>Django 1.1</li>
<li>psycopg2 2.0.8</li>
</ul>
<h2>Tested configurations</h2>
<h3>Apache with mod_wsgi</h3>
<p>This was the first configuration I tested. Apache was serving both the static files and dynamic content via mod_wsgi which ran in daemon mode with 5 processes and 1 thread per process.</p>
<h3>Nginx + Apache with mod_wsgi</h3>
<p>My preferred configuration for running django sites. Apache with mod_wsgi was used only for the dynamic content, requests to these urls were proxied by nginx. Static files were served by nginx directly.</p>
<h3>Nginx + fcgi</h3>
<p>Here nginx is used for serving the static content while the dynamic content was handled by FastCGI processes. I used all the defaults from the runfcgi management command and used a TCP socket instead of a socket file because I was bumping into issues with access to the socket file at large numbers of concurrent requests.</p>
<h3>Cherokee + SCGI</h3>
<p>This was set up from the Cherokee web based wizard for deploying django applications. Static files were served by Cherokee directly. I have to say this is by far the  easiest method of deploying Django applications in production environments.</p>
<h3>Cherokee + Apache with mod_wsgi</h3>
<p>This is essentially the same as Nginx + Apache and mod_wsgi except here Cherokee was used as a proxy and for serving static content. Since it&#8217;s the first time I&#8217;m using Cherokee everything was configured via the web based admin interface and all parameters were left to default values.</p>
<h3>Nginx + Cherrypy WSGI server</h3>
<p>Here I used the <a href="http://github.com/lincolnloop/django-cpserver">django-cpserver</a> management command to run the application in the Cherrypy WSGI server. 5 Instances of the WSGI server were running behind Nginx as a load balancer. Nginx was serving the static files.</p>
<h2>Configurations that are left out</h2>
<h3>Apache with mod_python</h3>
<p>This was left out because I couldn&#8217;t get consistent results at 250 concurrent requests and the application would often error out at this concurrency level. The benchmark already took a significant amount of my time and I&#8217;m not experienced with mod_python so I decided not to proceed with locating the problem or publishing any shaky results.</p>
<h3>uWSGI</h3>
<p>I tried to deploy the application on uWSGI with the Cherokee web based wizard. With the default configuration (1 process) the tests ran 4 times slower at high concurrency compared to the other configurations. Bumping up the number of process to 5 still didn&#8217;t yield comparable results. At 25 processes I got comparable results but memory usage skyrocketed. I still suspect I was doing something wrong here, so I didn&#8217;t publish the results.</p>
<h3>lighttpd</h3>
<p>Personally I avoid using lighty for a number of subjective reasons. When I have the time I may update this post with some configurations based on lighty, although I wouldn&#8217;t expect the results to be much different than the ones for the Nginx or Cherokee configurations.</p>
<h2>The results</h2>
<p><a href="http://spreadsheets.google.com/oimg?key=0ApNjbkQcMGV4dGdJOFVicHNGSFJGemFRT1pGMnVQMlE&amp;oid=5&amp;v=1263914004562"><img src="http://spreadsheets.google.com/oimg?key=0ApNjbkQcMGV4dGdJOFVicHNGSFJGemFRT1pGMnVQMlE&amp;oid=5&amp;v=1263914004562" alt="" width="436" height="192" /></a><br />
<a href="http://spreadsheets.google.com/oimg?key=0ApNjbkQcMGV4dGdJOFVicHNGSFJGemFRT1pGMnVQMlE&amp;oid=7&amp;v=1263914042360"><img src="http://spreadsheets.google.com/oimg?key=0ApNjbkQcMGV4dGdJOFVicHNGSFJGemFRT1pGMnVQMlE&amp;oid=7&amp;v=1263914042360" alt="" width="436" height="192" /></a><br />
<a href="http://spreadsheets.google.com/oimg?key=0ApNjbkQcMGV4dGdJOFVicHNGSFJGemFRT1pGMnVQMlE&amp;oid=6&amp;v=1263914066019"><img src="http://spreadsheets.google.com/oimg?key=0ApNjbkQcMGV4dGdJOFVicHNGSFJGemFRT1pGMnVQMlE&amp;oid=6&amp;v=1263914066019" alt="" width="435" height="192" /></a></p>
<h3>Memory usage</h3>
<p>I measured memory usage only at 250 concurrent requests. All the tests ran for 60 seconds, so you can work out where the load on the server happened from the graphs.</p>
<div id="attachment_133" class="wp-caption alignnone" style="width: 310px"><a href="http://basicverbs.com/wp-content/uploads/2010/01/mod_wsgi2.png"><img class="size-medium wp-image-133 " title="Apache with mod_wsgi" src="http://basicverbs.com/wp-content/uploads/2010/01/mod_wsgi2-300x225.png" alt="Apache with mod_wsgi" width="300" height="225" /></a><p class="wp-caption-text">Apache with mod_wsgi</p></div>
<div id="attachment_136" class="wp-caption alignnone" style="width: 310px"><a href="http://basicverbs.com/wp-content/uploads/2010/01/nginxmod_wsgi3.png"><img class="size-medium wp-image-136 " title="Nginx + Apache with mod_wsgi" src="http://basicverbs.com/wp-content/uploads/2010/01/nginxmod_wsgi3-300x225.png" alt="Nginx + Apache with mod_wsgi" width="300" height="225" /></a><p class="wp-caption-text">Nginx + Apache with mod_wsgi</p></div>
<div id="attachment_137" class="wp-caption alignnone" style="width: 310px"><a href="http://basicverbs.com/wp-content/uploads/2010/01/nginxcgi1.png"><img class="size-medium wp-image-137 " title="Nginx + FCGI" src="http://basicverbs.com/wp-content/uploads/2010/01/nginxcgi1-300x225.png" alt="Nginx + fcgi" width="300" height="225" /></a><p class="wp-caption-text">Nginx + FCGI</p></div>
<div id="attachment_138" class="wp-caption alignnone" style="width: 310px"><a href="http://basicverbs.com/wp-content/uploads/2010/01/nginxcp1.png"><img class="size-medium wp-image-138" title="Nginx + Cherrypy" src="http://basicverbs.com/wp-content/uploads/2010/01/nginxcp1-300x225.png" alt="Nginx + Cherrypy" width="300" height="225" /></a><p class="wp-caption-text">Nginx + Cherrypy</p></div>
<div id="attachment_139" class="wp-caption alignnone" style="width: 310px"><a href="http://basicverbs.com/wp-content/uploads/2010/01/cherokeewscgi1.png"><img class="size-medium wp-image-139" title="Cherokee + SCGI" src="http://basicverbs.com/wp-content/uploads/2010/01/cherokeewscgi1-300x225.png" alt="Cherokee + SCGI" width="300" height="225" /></a><p class="wp-caption-text">Cherokee + SCGI</p></div>
<div id="attachment_140" class="wp-caption alignnone" style="width: 310px"><a href="http://basicverbs.com/wp-content/uploads/2010/01/cherokeewsgi1.png"><img class="size-medium wp-image-140" title="Cherokee + Apache with mod_wsgi" src="http://basicverbs.com/wp-content/uploads/2010/01/cherokeewsgi1-300x225.png" alt="Cherokee + Apache with mod_wsgi" width="300" height="225" /></a><p class="wp-caption-text">Cherokee + Apache with mod_wsgi</p></div>
]]></content:encoded>
			<wfw:commentRss>http://basicverbs.com/benchmark-of-django-deployment-techniques/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
