<?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>Curia &#187; rails</title>
	<atom:link href="http://blog.curiasolutions.com/tag/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.curiasolutions.com</link>
	<description>Technology thoughts and ideas</description>
	<lastBuildDate>Wed, 16 Dec 2009 01:38:40 +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>The great web technology shootout &#8211; Round 3: Better, Faster, and Shinier</title>
		<link>http://blog.curiasolutions.com/2009/10/the-great-web-technology-shootout-round-3-better-faster-and-shinier/</link>
		<comments>http://blog.curiasolutions.com/2009/10/the-great-web-technology-shootout-round-3-better-faster-and-shinier/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 18:42:52 +0000</pubDate>
		<dc:creator>Seth</dc:creator>
				<category><![CDATA[F/OSS]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[pylons]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[turbogears]]></category>

		<guid isPermaLink="false">http://blog.curiasolutions.com/?p=409</guid>
		<description><![CDATA[[Note: This post is the continuation of a series. Please read Round 1 and Round 2 first if you are just now joining us.]
[Update 10/6: Slight updates to the Pylons test after some input from Ben. Added a couple new charts for you visual folks.]
As I briefly mentioned in Round 1, this whole thing came [...]]]></description>
			<content:encoded><![CDATA[<p>[Note: This post is the continuation of a series. Please read <a href="http://blog.curiasolutions.com/?p=172">Round 1</a> and <a href="http://blog.curiasolutions.com/?p=278">Round 2</a> first if you are just now joining us.]</p>
<p><strong>[Update 10/6: Slight updates to the Pylons test after some input from Ben. Added a couple new charts for you visual folks.]</strong></p>
<p>As I briefly mentioned in <a href="http://blog.curiasolutions.com/?p=172">Round 1</a>, this whole thing came about as an experiment to satisfy my own curiosity. Unfortunately, I wasn&#8217;t expecting these posts to draw the amount of attention they have been getting, and several people informed me of a few &#8220;issues&#8221; with the first round. Since my initial approach to this topic was somewhat casual, I didn&#8217;t really take the time to perform each test in a &#8220;proper scientific fashion.&#8221; Although this was clearly stated in the introduction to round one, it unfortunately resulted in performance estimations that were somewhat less than accurate.</p>
<p>After input from various people much smarter than myself, I quickly went to work tweaking my test environment and building &#8220;proper&#8221; test apps. In the midst of this, a conversation about PHP accelerators prompted me to put PHP under the spotlight, which brought about <a href="http://blog.curiasolutions.com/?p=278">Round 2</a> as an interim round. This gave me a chance to demonstrate the necessity of PHP acceleration, and only continued to solidify my opinion of PHP as an inferior web development language (remember, I just said <em>my opinion</em>).</p>
<p>Which brings us to Round 3. A lot of work has gone into &#8220;doing it right&#8221; this time, so I am fairly confident that these results are a much more accurate representation of each test subject&#8217;s performance estimations. Remember, benchmark test code typically has no real-world value, so &#8220;performance estimations&#8221; are about all I can promise here. <strong>Your mileage <em>will</em> vary.</strong> As a wise person once said:</p>
<blockquote><p>&#8220;All this benchmarking is doing is proving what we already know: More code takes longer to execute.&#8221; &#8211; Ben Bangert (dev lead of Pylons)</p></blockquote>
<p><span id="more-409"></span></p>
<p>&nbsp;</p>
<p>What you should know about Round 3:</p>
<ul>
<li>The hardware/software platform is the same as in <a href="http://blog.curiasolutions.com/?p=172">Round 1</a>.</li>
<li>Python v2.5.4 was used for all the Python tests. Ruby v1.8.6 was used for the Rails test.</li>
<li>Apache v2.2.3 was used, with <a href="http://code.google.com/p/modwsgi/" target="_blank">mod_wsgi</a> v2.5 for the Python tests and <a href="http://www.modrails.com/" target="_blank">Phusion Passenger</a> v2.2.5 for the Rails test.</li>
<li>Note that while the mod_wsgi tests in Round 1 were using &#8220;daemon mode&#8221;, the mod_wsgi tests here are using &#8220;embedded mode&#8221; which is often faster (although <a href="http://blog.dscpl.com.au/2009/03/load-spikes-and-excessive-memory-usage.html" target="_blank">not necessarily the recommended configuration)</a>.
<li>The Python component versions used here were: SQLAlchemy v0.5.6, Genshi v0.5.1, Mako v0.2.5, and Jinja 2.2.1.</li>
<li>ApacheBench was run with -n 10000 -c 10.</li>
<li>Each test was run several times to make sure that there were no anomalies, with the &#8220;optimum average&#8221; chosen as the numbers represented here.</li>
<li>In an attempt to try to make these tests more scientific, I am now including the source code for each test.</li>
</ul>
<p>&nbsp;</p>
<blockquote><h4>Plain WSGI – <a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/wsgi_test_src.zip">wsgi_test_src.zip</a></h4>
</blockquote>
<p>Let&#8217;s start with a basic &#8220;hello world&#8221; WSGI test to set the baseline:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The <span style="color: #ff0000;">'hello world'</span> test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">WSGIServer</span><span style="color: #66cc66;">/</span><span style="color: #cc66cc;">0.1</span>
Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1532.76</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Apache<span style="color: #66cc66;">/</span>2<span style="color: #66cc66;">.</span>2<span style="color: #66cc66;">.</span>3 <span style="color: #66cc66;">&#40;</span>mod_wsgi<span style="color: #66cc66;">&#41;</span>
Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">5549.73</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>As you can see, mod_wsgi allows Apache to put some serious muscle into Python&#8217;s WSGI. It&#8217;s no wonder that mod_wsgi is quickly becoming the de-facto standard for Apache Python deployment.</p>
<p>&nbsp;</p>
<blockquote><h4>TurboGears v2.0.3 – <a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/tg2_test_src.zip">tg2_test_src.zip</a></h4>
</blockquote>
<p>As I mentioned in Round 1, <a href="http://www.turbogears.org/" target="_blank">TurboGears</a> has quickly become my web framework of choice. Building a &#8220;best-of-breed&#8221; component stack on top of Pylons <a href="http://percious.com/blog/archives/31" target="_blank">may not be easy</a>, but <a href="http://percious.com/blog/archives/32" target="_blank">when it works</a> I believe it pays off immensely (e.g. Ubuntu).</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The <span style="color: #ff0000;">'hello world'</span> test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">935.13</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Genshi template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>genshi_hello<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">923</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">601.07</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Mako template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>mako_hello<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">932</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">723.18</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Jinja2 template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>jinja_hello<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">937</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">764.35</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Database query tests<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>raw_sql<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">1270</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">569.71</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>genshi_sql<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2409</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">388.96</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>mako_sql<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2418</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">515.07</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>jinja_sql<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2472</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">535.06</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>&nbsp;</p>
<blockquote><h4>TurboGears v2.1a1 – <a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/tg21_test_src.zip">tg21_test_src.zip</a></h4>
</blockquote>
<p>The TurboGears community is alive and well, and just before finishing this post the release of v2.1 Alpha 1 was announced. Significant improvements were made to TG&#8217;s <a href="http://percious.com/blog/archives/33" target="_blank">object dispatch</a>, so I was excited to see what the new numbers would look like.</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The <span style="color: #ff0000;">'hello world'</span> test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">11</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1118.92</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Genshi template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>genshi_hello<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">923</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">713.97</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Mako template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>mako_hello<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">932</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">812.64</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Jinja2 template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>jinja_hello<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">937</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1000.98</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Database query tests<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>raw_sql<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">1270</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">673.04</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>genshi_sql<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2409</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">433.45</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>mako_sql<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2418</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">601.89</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>jinja_sql<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2472</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">630.66</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>As you can see, the future of TurboGears looks very bright, and I only expect these numbers to get better as the final 2.1 release approaches (expected in Q1 2010).</p>
<p>&nbsp;</p>
<blockquote><h4>Pylons v0.9.7 – <a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/pylons_test_src.zip">pylons_test_src.zip</a></h4>
</blockquote>
<p><a href="http://www.pylonshq.com/" target="_blank">Pylons</a> is the foundation which TurboGears is built upon, and for those who don&#8217;t need all &#8220;the extras&#8221; it is an excellent choice.</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The <span style="color: #ff0000;">'hello world'</span> test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hello<span style="color: #66cc66;">/</span>index
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">2593.47</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Mako template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hello<span style="color: #66cc66;">/</span>hello
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">932</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1737.03</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Database query tests<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hello<span style="color: #66cc66;">/</span>raw_sql
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">1270</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">964.07</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hello<span style="color: #66cc66;">/</span>hellodb
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2418</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">831.26</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>&nbsp;</p>
<blockquote><h4>Django v1.1 – <a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/django_test_src.zip">django_test_src.zip</a></h4>
</blockquote>
<p>While <a href="http://www.djangoproject.com/" target="_blank">Django</a> is probably Python&#8217;s most popular web framework, I have never really clicked with it. Its way of doing things is significantly different than TG/Pylons, but if you don&#8217;t mind its &#8220;<a href="http://docs.djangoproject.com/en/dev/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names" target="_blank">MTV</a>&#8221; architectural pattern and can survive without SQLAlchemy (although there are hacks), it is a very capable framework.</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The <span style="color: #ff0000;">'hello world'</span> test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hello
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">3376.48</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Django template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hellos
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">936</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1781.43</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Database query test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hellodb
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2476</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">972.11</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>&nbsp;</p>
<blockquote><h4>Bottle 0.5.8 – <a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/bottle_test_src.zip">bottle_test_src.zip</a></h4>
</blockquote>
<p><a href="http://bottle.paws.de/" target="_blank">Bottle</a> caught my attention a few months ago while surveying the WSGI landscape for an alternative to PHP when building websites that only require a few pieces of dynamic functionality. As a &#8220;micro-framework&#8221;, it does an excellent job at bridging the gap between &#8220;pure WSGI&#8221; and its &#8220;feature-rich&#8221; big brothers.</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The <span style="color: #ff0000;">'hello world'</span> test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">5545.96</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Mako template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hello
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">923</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">3588.04</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Database query test <span style="color: #66cc66;">&#40;</span>SQLAlchemy<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hellodb
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2413</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1479.54</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>As you can see, there was practically no difference in speed between Bottle and pure WSGI in a basic &#8220;hello world&#8221; test. Even with the addition of Mako and SQLAlchemy, Bottle performed significantly faster than a bare Pylons or Django setup.</p>
<p>(Note: Mako template inheritance was not used in the Bottle Mako test.)</p>
<p>&nbsp;</p>
<blockquote><h4>Ruby on Rails v2.3.3 – <a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/rails_test_src.zip">rails_test_src.zip</a></h4>
</blockquote>
<p>What web technology shootout would be complete without <a href="http://www.rubyonrails.org/" target="_blank">Rails</a>? Although I am not a Rails fan (mostly because I can&#8217;t stand Ruby), I believe that in many ways we owe much of the popularity and success of the web framework movement to Rails.</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The <span style="color: #ff0000;">'hello world'</span> test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hello<span style="color: #66cc66;">/</span>hello
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1048.18</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Rails template test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hello<span style="color: #66cc66;">/</span>hellos
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">937</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">949.54</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span>
&nbsp;
&nbsp;
Database query test<span style="color: #66cc66;">:</span>
&nbsp;
<span style="color: #006600;">Document</span> Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>hello<span style="color: #66cc66;">/</span>hellodb
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2482</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">734.18</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>(Note: I think my version of Ruby was using a newer version of the SQLite3 library than my version of Python. This may or may not have given Rails an advantage on the database query test.)</p>
<p>&nbsp;</p>
<p>For those of you who like charts, here&#8217;s a comparison of the &#8220;return hello world&#8221; test results for each framework:</p>
<div id="attachment_531" class="wp-caption aligncenter" style="width: 566px"><a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/hello_world_test.png"><img src="http://blog.curiasolutions.com/wp-content/uploads/2009/10/hello_world_test.png" alt="The return hello world test chart" title="Hello World Test" width="556" height="352" class="size-full wp-image-531" /></a><p class="wp-caption-text">The return hello world test chart</p></div>
<p>And here&#8217;s a comparison of the template test:</p>
<div id="attachment_532" class="wp-caption aligncenter" style="width: 566px"><a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/template_test.png"><img src="http://blog.curiasolutions.com/wp-content/uploads/2009/10/template_test.png" alt="The template test chart" title="Template Test" width="556" height="263" class="size-full wp-image-532" /></a><p class="wp-caption-text">The template test chart</p></div>
<p>Finally, here&#8217;s the template test with the database query added:</p>
<div id="attachment_530" class="wp-caption aligncenter" style="width: 566px"><a href="http://blog.curiasolutions.com/wp-content/uploads/2009/10/database_test.png"><img src="http://blog.curiasolutions.com/wp-content/uploads/2009/10/database_test.png" alt="Template test with database query" title="Database Query" width="556" height="264" class="size-full wp-image-530" /></a><p class="wp-caption-text">Template test with database query</p></div>
<p>&nbsp;</p>
<h4>Closing thoughts</h4>
<ul>
<li>Gone are the days of Rails as &#8220;the one framework to rule them all.&#8221; C&#8217;mon guys, it&#8217;s not 2005 anymore.</li>
<li>Python has gotten a lot of flak from other language camps for its abundance of web frameworks. While some Pythonists have been embarrassed by this, I only see it as proof of Python&#8217;s success as a language. My retort would be: &#8220;If it was as easy to write a web framework in your language as it is in Python, you&#8217;d have the same problem!&#8221;</li>
</ul>
<p>&nbsp;</p>
<h5>Coming soon: &#8220;Round 4: Micro-frameworks &mdash; Quick &#038; Dirty, and leaving PHP in the dust!&#8221;</h5>
<p>(Note: Please don&#8217;t leave benchmarking requests as comments. If you&#8217;d like me to take a look at your favorite framework, direct message me on twitter. Thanks!)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.curiasolutions.com/2009/10/the-great-web-technology-shootout-round-3-better-faster-and-shinier/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>The great web technology shootout &#8211; Round 1: A quick glance at the landscape</title>
		<link>http://blog.curiasolutions.com/2009/09/the-great-web-development-shootout/</link>
		<comments>http://blog.curiasolutions.com/2009/09/the-great-web-development-shootout/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 05:29:28 +0000</pubDate>
		<dc:creator>Seth</dc:creator>
				<category><![CDATA[F/OSS]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[turbogears]]></category>

		<guid isPermaLink="false">http://blog.curiasolutions.com/?p=172</guid>
		<description><![CDATA[[Update: Some of the results here ended up being less than accurate. Please see Round 3 for an explanation (and updated tests).]
Recently I went on a benchmarking spree and decided to throw ApacheBench at a bunch of the different web development technology platforms I interact with on a day-to-day basis. The results were interesting enough [...]]]></description>
			<content:encoded><![CDATA[<p><strong>[Update: Some of the results here ended up being less than accurate. Please see <a href="http://blog.curiasolutions.com/?p=409">Round 3</a> for an explanation (and updated tests).]</strong></p>
<p>Recently I went on a benchmarking spree and decided to throw <a href="http://en.wikipedia.org/wiki/ApacheBench" target="_blank">ApacheBench</a> at a bunch of the different web development technology platforms I interact with on a day-to-day basis. The results were interesting enough to me that I decided I&#8217;d take a post to share them here.</p>
<p><strong>Disclaimer: The following test results should be taken with a <em>massive</em> grain of salt.</strong> If you know anything about benchmarking, you will know that the slightest adjustments have the potential to change things drastically. While I have tried to perform each test as fairly and accurately as possible, it would be foolish to consider these results as scientific in any way. <strong>It should also be noted that my goal here was not to see how fast each technology performs at its most optimized configuration, but rather what a minimal out-of-the-box experience looks like.</strong></p>
<p>Test platform info:</p>
<ul>
<li>The hardware was an Intel Core2Quad Q9300, 2.5Ghz, 6MB Cache, 1333FSB, 2GB DDR RAM.</li>
<li>The OS was CentOS v5.3 32-bit with a standard Apache Webserver setup.</li>
<li> ApacheBench was used with only the -n and -c flags (1000 requests for the PHP frameworks, 5000 requests for everything else).	</li>
<li> Each ApacheBench test was run 5-10 times, with the &#8220;optimum average&#8221; chosen as the numbers represented here.</li>
<li>The PHP tests were done using the standard Apache PHP module.</li>
<li>The mod_wsgi tests were done in daemon mode set to 2 processes/15 threads.</li>
<li>The SQL tests were done with mysqli ($mysql->query()) on PHP, and SQLAlchemy (conn.execute()) on Python fetching and printing 5 rows of data from a sample database.</li>
</ul>
<p>&nbsp;</p>
<h4>Apache v2.2.3</h4>
<p>We will start with the raw Apache benchmark.</p>
<p>For this test, Apache loaded a simple HTML file with random text:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">6537</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">8356.23</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>As expected, Apache is lightning fast.</p>
<p>Ok, so now that we&#8217;ve set the high water mark, let&#8217;s take a look at some popular web technology platforms&#8230;<span id="more-172"></span></p>
<p>&nbsp;</p>
<h4>PHP v5.2.8</h4>
<p>For this test, I created a PHP file that simply printed the $_SERVER array and some random text:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">6135</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">2812.22</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Next, I decided to add some mysqli() code to connect to a database and print out a few rows of data:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">283</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">2135.46</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Not at all bad, but who really wants to build a webapp using plain old PHP anymore?</p>
<p>Next I decided to test the two PHP frameworks that I am most familiar with.</p>
<p>&nbsp;</p>
<h4>CakePHP v1.2.5</h4>
<p>For this test, I did a basic CakePHP install, and added a route that printed &#8220;hello world&#8221; from a template:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">944</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">42.00</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>As you can see, frameworks can be a blessing and a curse. On a side note, CakePHP was the only test that gave me failed requests.</p>
<h4>Kohana v2.3.4</h4>
<p>For this test, I did a basic install and loaded Kohana&#8217;s default welcome/index setup (which seemed lightweight enough to me to qualify as the test focal point):</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">1987</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">100.11</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Kohana fared much better than CakePHP, but it appears as though PHP&#8217;s speed breaks down quickly once you start building a framework around it.</p>
<p>&nbsp;</p>
<h4>Python v2.5.4</h4>
<p>Unlike PHP, Python wasn&#8217;t specifically created for the web. However, several years ago the <a href="http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface" target="_blank">WSGI spec</a> was introduced which makes building web applications with Python a breeze. There are many different ways to depoly a WSGI app, but my tests were limited to Python&#8217;s built-in WSGIServer, and Apache&#8217;s <a href="http://code.google.com/p/modwsgi/" target="_blank">mod_wsgi</a>.</p>
<h4>WSGIServer</h4>
<p>For this test, I used WSGI.org&#8217;s <a href="http://hg.moinmo.in/moin/1.8/raw-file/tip/wiki/server/test.wsgi" target="_blank">test.wsgi</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">4123</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1658.35</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>These results were quite impressive to me, considering that this is pure Python at work.</p>
<h4>mod_wsgi</h4>
<p>mod_wsgi is Apache&#8217;s module to process WSGI scripts. This test used the exact same script as the previous WSGIServer example:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">9552</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">3994.30</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Don&#8217;t look now, but those results are better than the vanilla PHP test!</p>
<p>Next, I added SQLAlchemy imports to the test file and did a conn.execute(), in an attempt to try to mimic the PHP mysqli() test:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">10212</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">3379.87</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>I expected to lose quite a bit of speed with the introduction of an ORM, but it looks like SQLAlchemy is quite fast. These results were still over 1,000reqs/s more than the PHP example.</p>
<h4>TornadoServer</h4>
<p>There&#8217;s been a lot of buzz lately about the new <a href="http://www.tornadoweb.org/" target="_blank">TornadoServer</a>, so I thought I&#8217;d throw it in the mix. This test uses their basic &#8220;hello world&#8221; example:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">3330.00</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Nothing shocking here at first glance, but the Tornado is built to handle extreme loads. So, I increased the concurrency to 1,000 and threw 10,000 requests at it:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Concurrency Level<span style="color: #66cc66;">:</span>      <span style="color: #cc66cc;">1000</span>
<span style="color: #0000ff;">COMPLETE</span> requests<span style="color: #66cc66;">:</span>      <span style="color: #cc66cc;">10000</span>
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">3288.15</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Almost exactly the same results! On a side note, none of the other tests subjects were able to handle a concurrency of 1,000.</p>
<p>&nbsp;</p>
<h4>TurboGears v2.0.3 (mod_wsgi)</h4>
<p><a href="http://www.turbogears.com/" target="_blank">TurboGears</a> has quickly become my framework of choice, so naturally it was the first Python framework I tested.</p>
<p>For this test I setup a default quickstart project, and then added a hello() controller method which simply returned a &#8220;hello world&#8221; string:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">11</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">470.18</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Next, I added a simple Genshi template with 1 level of inheritance:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">1351</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">143.26</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>While those results are not terrible, they should encourage you to check out the other templating options.</p>
<p>Next, I performed the same test with Mako:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">1534</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">394.41</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>As you can see, Mako is significantly faster than Genshi.</p>
<p>TurboGears also supports Jinja2, so I thought I&#8217;d also see how it held up:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">1020</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">401.04</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>I was not expecting Jinja2 to be faster than Mako, so I am not entirely sure about these results. However, the difference is only slight, and might have something to do with the fact that the dotted template names finder is disabled for Jinja templates.</p>
<h4>Pylons v0.9.7 (mod_wsgi)</h4>
<p>Mark Ramm (the current development lead of TurboGears) has been quoted as saying &#8220;TurboGears is to Pylons as Ubuntu is to Debian.&#8221; With that in mind, I naturally wanted to see how much speed I was losing with TurboGears&#8217; &#8220;additions&#8221;.</p>
<p>For this test I tried to mimic the first TurboGears test (basic layout, returning a string):</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">11</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1961.00</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>While I was expecting a gain from TurboGears&#8217; omissions, I wasn&#8217;t quite expecting over four times the increase. I can only assume that the bare Pylons setup is pretty minimal, while TurboGears bootstraps a lot of stuff on for you by default.</p>
<p>Duplicating the Mako test in Pylons was also quite fast:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">9743</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">1183.39</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<h4>Bottle v0.5.7 (mod_wsgi)</h4>
<p><a href="http://bottle.paws.de/" target="_blank">Bottle</a> caught my attention recently as a minimalistic Python web framework, so I thought I&#8217;d put it through the grind as well.</p>
<p>For this test, I used their simple &#8220;hello world&#8221; example:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">12</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">3912.43</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>As you can see, Bottle is very close to bare WSGI as far as speed goes. On a side note, adding a sample template using Bottle&#8217;s default templating package didn&#8217;t seem to change these numbers at all.</p>
<p>Next I tested Bottle with its templating system switched to Mako:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">41</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">3134.61</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Then I added a SQLAlchemy and performed a query:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">9374</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">2503.27</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>What was exciting to me about this test was that I found myself looking at a minimal Python framework equipped with a full templating system and ORM which all performed faster than the PHP+mysqli() test.</p>
<h4>Django v1.1 (mod_wsgi)</h4>
<p>I don&#8217;t use <a href="http://www.djangoproject.com/" target="_blank">Django</a>, but I thought it would be worth including in this report. This is a basic Django setup printing out a simple hello world template:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">1471</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">564.41</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>As expected, a minimal Django setup is quite fast. (Note: This test included a SQLite database query.)</p>
<p>&nbsp;</p>
<h4>Ruby On Rails v2.2.3 (mod_passenger)</h4>
<p>I also don&#8217;t use <a href="http://rubyonrails.org/" target="_blank">Rails</a>, but I figured this report would be incomplete without Rails on the list. So, I took <a href="http://gems.mediatemple.net/testapp_rails.tgz">MediaTemple&#8217;s Rails test app</a> and loaded up a test page:</p>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">1291</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">433.57</span> <span style="color: #66cc66;">&#91;</span>#<span style="color: #66cc66;">/</span>sec<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>mean<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Note that the test app used here is doing a little bit more than just returning &#8220;Hello World&#8221;.</p>
<p>&nbsp;</p>
<h4>My Conclusions</h4>
<p>As I said in the disclaimer, to arrive at any sort of decisive conclusions based on these numbers alone would be foolish. However, here is what all of this left me thinking:</p>
<ul>
<li>All of these technologies performed adequately for use with most projects.</li>
<li>CakePHP was the only test that produced less than 100 requests per second. However, there are many articles available on optimizing CakePHP.</li>
<li>These results made me wish I had moved away from PHP much earlier in my web development carrier. There are just better options these days when it comes to choosing a web development language (imho). If you <em>must</em> use PHP for a large project, I strongly suggest that you look into <a href="http://en.wikipedia.org/wiki/PHP_accelerator" target="_blank">an accelerator</a>.</li>
<li>The Bottle+Mako+SQLAlchemy results struck me as an extremely minimal drop-in replacement for simple PHP sites.</li>
<li>mod_wsgi is a huge winner in deploying Python webapps. Way to go Graham!</li>
<li>Do your own bencharking, because <em>your mileage <strong>will</strong> vary</em>!</li>
</ul>
<p>&nbsp;</p>
<h5>Like what you&#8217;ve seen here? Then why not check out <a href="http://blog.curiasolutions.com/?p=278">Round 2</a>?</h5>
<p>(Note: Please don&#8217;t leave benchmarking requests as comments. If you&#8217;d like me to take a look at your favorite framework, direct message me on twitter. Thanks!)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.curiasolutions.com/2009/09/the-great-web-development-shootout/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
