<?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; php</title>
	<atom:link href="http://blog.curiasolutions.com/tag/php/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>Python as a PHP replacement?</title>
		<link>http://blog.curiasolutions.com/2009/11/python-as-a-php-replacement/</link>
		<comments>http://blog.curiasolutions.com/2009/11/python-as-a-php-replacement/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 18:11:50 +0000</pubDate>
		<dc:creator>Seth</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.curiasolutions.com/?p=637</guid>
		<description><![CDATA[I recently sat down to coffee with a new acquaintance of mine who spends much of his time implementing F/OSS projects at non-profit organizations, and who had just stepped into a lead web developer position using PHP. After sharing pleasantries we began trading stories and talking about each of our &#8220;tools of the trade.&#8221; When [...]]]></description>
			<content:encoded><![CDATA[<p>I recently sat down to coffee with a new acquaintance of mine who spends much of his time implementing F/OSS projects at non-profit organizations, and who had just stepped into a lead web developer position using PHP. After sharing pleasantries we began trading stories and talking about each of our &#8220;tools of the trade.&#8221; When I mentioned that I used to do most of my web development in PHP, but have spent the past year or so trying to move as completely as possible to Python, his response was: &#8220;Huh, I have never really thought of Python as a PHP replacement.&#8221;</p>
<p>Now, this guy hasn&#8217;t exactly been living under a rock for the past 10 years—his resume was quite impressive and included projects in a number of different programming languages; But as you can imagine, I was rather surprised by his response, and it made me wonder: Has the Python community really been that bad at promoting the strengths of Python for web development? Or, does the nirvana experienced by switching from a language like PHP to Python just make us so at peace with the world that we forget the hordes of developers still stuck with C-style syntax? Either way, it got me thinking about a few of the reasons why <em>I</em> decided to switch from PHP to Python; and why I not only see Python as an excellent PHP replacement, but am surprised it is such a &#8220;best-kept secret&#8221; for web development.</p>
<p>There are already plenty of pages out there discussing <a href="http://wiki.python.org/moin/PythonVsPhp" target="_blank">Python vs. PHP as a language</a>, so I probably won&#8217;t get too technical here. I also want to try avoid turning this into a &#8220;Python is better than PHP because&#8230;&#8221; rant (for more on that, please see the end of this post), so I will simply share with you a few of the main reasons why <em>I</em> decided to replace PHP with Python as <em>my</em> primary language for web development:</p>
<p><span id="more-637"></span></p>
<h4>» Python is more flexible than PHP</h4>
<p>Python was engineered from the beginning to be a general purpose programming language. PHP on the other hand was written to overcome many of the &#8220;limitations&#8221; of the <a href="http://en.wikipedia.org/wiki/Cgi-bin" target="_blank">cgi-bin</a>. This should say a lot about the &#8220;soul&#8221; of each language, but the conclusion I have come to is:</p>
<ul>
<li>PHP is meant to do web things really well</li>
<li>Python is meant to do most things really well</li>
</ul>
<p>Sure, these days you <em>could</em> write a desktop GUI in PHP, but it would most likely <em>not</em> be the right tool for the job (and you&#8217;d probably get laughed at). On a somewhat related note: many PHP developers I know find themselves switching between PHP for their website tasks, and a variety of other languages for other tasks (Shell Scripting for command-line scripts, Perl for text processing, etc.). As a Python programmer, I can typically stick to <em>one programming language</em> no matter what the task at hand requires (especially when armed with <a href="http://ipython.scipy.org/" target="_blank">iPython</a>).</p>
<p>Now, the obvious argument for PHP at this point is: &#8220;But wait, since PHP was written specifically for the web, shouldn&#8217;t that actually give it <em>more</em> credibility as the right tool for the web job?&#8221; Well, 5 or 10 years ago I might have agreed with you, but web development has changed a lot in the past few years (not to mention the introduction of Python&#8217;s <a href="http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface" target="_blank">WSGI spec</a>).</p>
<p>The internet as a platform has grown and mutated drastically and now requires much more than &#8220;a server-side extension to HTML.&#8221; We are now in an age of full-blown internet <em>applications</em>, which require a true &#8220;application-level&#8221; language. In my opinion, PHP has only recently begun to move in that direction with the v5.3 release (as well as updates expected in PHP 6). That alone should give you pause when pondering PHP&#8217;s ability to &#8220;keep up&#8221; with the growth of the web.</p>
<p>In short, the internet continues to transform into an arena that is much less of a website platform, and much more of an application platform. To me, this makes a general purpose language such as Python the obvious choice for &#8220;future-proof&#8221; internet development.</p>
<h4>» Python is typically faster than PHP, <span style="text-decoration: line-through;">even</span> especially on the web</h4>
<p>You might find PHP beating out Python in a simple &#8220;hello world&#8221;-type test, but &#8220;real-world&#8221; applications will typically run much faster in Python. In a Web 2.0 world where everyone has broadband, speed is now an important factor in keeping your visitors happy.</p>
<p>In addition to &#8220;raw, under-the-hood&#8221; speed, Python&#8217;s language philosophy means it will typically <a href="http://groups.google.com/group/comp.lang.python/msg/83907b65bdee30f6" target="_blank">scale better than PHP</a> (although this can be argued a million different ways, since scalability usually involves much more than the language).</p>
<p>I&#8217;ve already done <a href="http://blog.curiasolutions.com/2009/09/the-great-web-development-shootout/" target="_blank">benchmarks</a> comparing a few popular web frameworks, but if you&#8217;re still curious I&#8217;d suggest you <a href="http://www.google.com/search?q=is+python+or+php+faster%3F" target="_blank">dig around with Google</a> for a while.</p>
<h4>» Python is easier to read and maintain than PHP</h4>
<p>Any veteran programmer will tell you that code <em>readability</em> plays a huge factor in code <em>maintainability</em>. With that in mind, Python was designed with some pretty strict syntax rules in regards to code-blocks and whitespace. While this may initially frustrate programmers who are used to a looser &#8220;bracket-encapsulated&#8221; language, it actually forces you to write more readable (and therefore, more maintainable) code.</p>
<p>Other than readability, Python&#8217;s clean syntax also means:</p>
<ul>
<li>You can write more code with less errors (because they&#8217;re so easy to spot). This often comes as a pleasant surprise to programmers migrating from C-style languages (take <a href="http://www.python.org/about/success/esr/" target="_blank">Eric Raymond</a> for example).</li>
<li>You end up typing less — No more semicolons or brackets, and fewer parentheses.</li>
<li>Your eyes don&#8217;t have to move around as much to figure out what&#8217;s going on.</li>
<li>Your first guess about what&#8217;s happening in a code-block is usually correct.</li>
</ul>
<p>When you have time to kill, I&#8217;d recommend a stroll through <a href="http://rosettacode.org/wiki/Main_Page" target="_blank">Rosetta Code</a> to compare how different languages &#8220;look&#8221; when tackling the same problem. Unless you just love brackets, I think you&#8217;ll find the non C-style syntaxes much easier to read.</p>
<h4>» Python is more consistent than PHP</h4>
<p>Continuing somewhat in the vein of readability is the topic of consistency. Since PHP&#8217;s lack of consistency has already been studied exhaustively by the Perl folks, I will spare you my rant and suggest you <a href="http://tnx.nl/php.html" target="_blank">read theirs</a>.</p>
<p>As a side note on this topic: I often hear PHP programmers talk about how awesome PHP&#8217;s documentation is in that you can open a web browser and just type &#8220;php.net/some_function&#8221; to get help. Well, documentation recall usually isn&#8217;t that big of a deal for me (because I have a somewhat photographic memory), but I will say that after switching to Python I found myself turning to its documentation <em>significantly</em> less than I had with PHP, simply because I didn&#8217;t have to keep reminding myself whether that infrequently used function was named some_function or somefunction. With Python, the function/method I need is usually named <em>exactly</em> what I expect it to be named, and returns <em>exactly</em> what I expect it to return.</p>
<p>Oh, and don&#8217;t even get me started on PHP&#8217;s recent <a href="http://blog.fedecarg.com/2008/10/28/php-namespaces-controversy/" target="_blank">namespace</a> <a href="http://michaelkimsal.com/blog/disappointed-with-php-namespace-seperator-decision/" target="_blank">decision</a>.</p>
<p>&nbsp;</p>
<h4 style="text-align: center;">» However, PHP still excels in a few areas «</h4>
<p>Having said all of that, there are a few areas where I believe PHP may still shine brighter than Python:</p>
<h4>» PHP hosting support <span style="text-decoration: line-through;">is</span> may be more prevalent than Python</h4>
<p>It&#8217;s practically unheard of to find yourself on a web host that doesn&#8217;t support PHP out of the box. However, this is becoming less and less of an issue since most Python web applications can now be deployed using tools such as FastCGI or mod_proxy (as opposed to the popular <a href="http://code.google.com/p/modwsgi/" target="_blank">mod_wsgi</a> setup, which often requires root access to configure). These days any &#8220;reputable&#8221; web host is probably going to support some sort of strategy for deploying Python web applications. Of course, this only really applies to shared hosting environments without root access. If you&#8217;ve got a VPS or dedicated server you&#8217;re fine.</p>
<h4>» PHP is arguably &#8220;more seasoned&#8221; on the web than Python</h4>
<p>The communities behind projects like Drupal and WordPress really stand out to me as examples of the maturity of PHP on the web. Although similar Python web projects have been slowly emerging (and <a href="http://plone.org/" target="_blank">Plone</a> has been around for years, if that&#8217;s your cup of tea), they don&#8217;t really compete yet in my opinion.</p>
<p>Of course, I am only talking about specific web projects here. Language wise, Python has been around longer than PHP. Web 2.0 framework wise, Python&#8217;s offerings have been around about as long as PHP&#8217;s (pretty much every language had its own answer to Ruby on Rails in 2005).</p>
<h4>» PHP <em>seems</em> easier than Python at first (and might be for simple deployments)</h4>
<p>There&#8217;s something magical about throwing together a few quick index.php/about.php/contact.php files and uploading them to the httpdocs directory of your webserver and it &#8220;just working.&#8221; A lot of simple websites have no need for acronyms like MVC, ORM, and DRY, and in those cases PHP is an excellent &#8220;server-side extension&#8221; to HTML. However, if and when you begin to scale, you&#8217;ll either find yourself switching to a full-blown framework, or throwing one together to help facilitate your growth. At that point, you&#8217;ll probably begin discovering the &#8220;dark corners&#8221; of PHP, and may find yourself wishing you had &#8220;done it right&#8221; the first time.</p>
<p>&nbsp;</p>
<h4 style="text-align: center;">» So, which is better? «</h4>
<p>Remember, the point of this post is to solidify the fact that Python can be an excellent PHP <em>replacement</em>. When it comes to programming languages, &#8220;better&#8221; is often more a case of personal preference than anything else. However, to <em>me</em> the points discussed above make Python the better choice when it comes to what <em>I</em> like in a web development language.</p>
<p>So, is Python a better web development language than PHP?<br />
Well, does Nike make a better shoe than Adidas?</p>
<p>The most honest answer is probably: &#8220;It depends.&#8221; Python definitely has some significant advantages over PHP in certain circumstances, but the same could probably be said of PHP in other circumstances (although limited to the web I imagine).</p>
<p>&nbsp;</p>
<p>I hope this post has encouraged you PHP programmers out there to take another look at Python. It may take some getting used to (Python&#8217;s way of doing things is inherently quite different than PHP&#8217;s), but you will probably find yourself thanking me later.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.curiasolutions.com/2009/11/python-as-a-php-replacement/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Reorganizing data with list &amp; dict comprehensions</title>
		<link>http://blog.curiasolutions.com/2009/10/reorganizing-data-with-list-dict-comprehensions/</link>
		<comments>http://blog.curiasolutions.com/2009/10/reorganizing-data-with-list-dict-comprehensions/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 03:58:59 +0000</pubDate>
		<dc:creator>Seth</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.curiasolutions.com/?p=538</guid>
		<description><![CDATA[While writing scripts, I frequently run into the issue of needing to re-arrange sets of data into a more &#8220;process friendly&#8221; format. A common issue I encounter is needing to turn a list (array) into a dictionary (associative array) or vice versa. More often than not, I find myself needing to be able to access [...]]]></description>
			<content:encoded><![CDATA[<p>While writing scripts, I frequently run into the issue of needing to re-arrange sets of data into a more &#8220;process friendly&#8221; format. A common issue I encounter is needing to turn a list (array) into a dictionary (associative array) or vice versa. More often than not, I find myself needing to be able to access list elements by a key, but since they aren&#8217;t setup in a dictionary I have to pull out a looping technique to reorganize the data for this to be possible.</p>
<p>Take the following set of data for example:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'John Smith'</span>, <span style="color: #483d8b;">'admin'</span><span style="color: black;">&#93;</span>,
 <span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">'Jane Doe'</span>, <span style="color: #483d8b;">'superuser'</span><span style="color: black;">&#93;</span>,
 <span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>, <span style="color: #483d8b;">'Sam Jones'</span>, <span style="color: #483d8b;">'user'</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span></pre></div></div>

<p>What we have here is a few rows of user data. In this example, the data is in a Python list (which in PHP would be an array).</p>
<p>In PHP, this would look something like (using print_r):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">Array</span> <span style="color: #009900;">&#40;</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">Array</span> <span style="color: #009900;">&#40;</span>
        <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span>
        <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> John Smith
        <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> admin
    <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">Array</span> <span style="color: #009900;">&#40;</span>
        <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">2</span>
        <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> Jane Doe
<span style="color: #666666; font-style: italic;"># (...etc...)</span></pre></div></div>

<p>So, what if I found myself writing some code that needed to be able to access each record by its first value, which in this case would be the user_id? <span id="more-538"></span></p>
<p>Well, in PHP the easiest way to make this happen would be a good-old-fashioned <em>foreach</em> loop:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$val</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$out</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$val</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$val</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Not very &#8220;sexy&#8221; for something I find myself having to more often than I would like, but it works nonetheless.</p>
<p>Now, here&#8217;s where the beauty of Python kicks in. Python has a built-in feature called &#8220;comprehension&#8221; which allows you to modify and/or convert sets of data quickly and easily.</p>
<p>Remember what our original data set looks like? Here&#8217;s a refresher:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> row
<span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'John Smith'</span>, <span style="color: #483d8b;">'admin'</span><span style="color: black;">&#93;</span>,
 <span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">'Jane Doe'</span>, <span style="color: #483d8b;">'superuser'</span><span style="color: black;">&#93;</span>,
 <span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>, <span style="color: #483d8b;">'Sam Jones'</span>, <span style="color: #483d8b;">'user'</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Now, in Python all we need to do is use the dictionary comprehension:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> out = <span style="color: black;">&#123;</span>val<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>: val <span style="color: #ff7700;font-weight:bold;">for</span> val <span style="color: #ff7700;font-weight:bold;">in</span> row<span style="color: black;">&#125;</span> <span style="color: #808080; font-style: italic;"># Python 3.X</span>
<span style="color: #808080; font-style: italic;"># (or, for Python 2.X)</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> out = <span style="color: #008000;">dict</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>val<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, val<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> val <span style="color: #ff7700;font-weight:bold;">in</span> row<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Python 2.4+</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> out
<span style="color: black;">&#123;</span><span style="color: #ff4500;">1</span>: <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'John Smith'</span>, <span style="color: #483d8b;">'admin'</span><span style="color: black;">&#93;</span>,
 <span style="color: #ff4500;">2</span>: <span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">'Jane Doe'</span>, <span style="color: #483d8b;">'superuser'</span><span style="color: black;">&#93;</span>,
 <span style="color: #ff4500;">3</span>: <span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>, <span style="color: #483d8b;">'Sam Jones'</span>, <span style="color: #483d8b;">'user'</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span></pre></div></div>

<p>See how easy that was?</p>
<p>And what if I had a dictionary in the above format, and needed to turn it into the type of list I had previously? Well, I could simply use the list comprehension to re-generate this set of data as a list:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#91;</span>val <span style="color: #ff7700;font-weight:bold;">for</span> val <span style="color: #ff7700;font-weight:bold;">in</span> out.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'John Smith'</span>, <span style="color: #483d8b;">'admin'</span><span style="color: black;">&#93;</span>,
 <span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">'Jane Doe'</span>, <span style="color: #483d8b;">'superuser'</span><span style="color: black;">&#93;</span>,
 <span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>, <span style="color: #483d8b;">'Sam Jones'</span>, <span style="color: #483d8b;">'user'</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span></pre></div></div>

<p>This is an extremely simple comprehension example. For a deeper look, check out Wikipedia&#8217;s <a href="http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Functional_programming" target="_blank">Python syntax page</a> or the <a href="http://docs.python.org/3.1/tutorial/datastructures.html" target="_blank">official Python documentation</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.curiasolutions.com/2009/10/reorganizing-data-with-list-dict-comprehensions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The great web technology shootout &#8211; Round 2: PHP deserves a helping hand</title>
		<link>http://blog.curiasolutions.com/2009/09/the-great-web-technology-shootout-round-2-php-deserves-a-helping-hand/</link>
		<comments>http://blog.curiasolutions.com/2009/09/the-great-web-technology-shootout-round-2-php-deserves-a-helping-hand/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 06:53:41 +0000</pubDate>
		<dc:creator>Seth</dc:creator>
				<category><![CDATA[F/OSS]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.curiasolutions.com/?p=278</guid>
		<description><![CDATA[[Note: This post is the continuation of a series. Please read Round 1 first if you are just now joining us.]
In Round 1, PHP was looking like quite the tortoise of the group. However, if you&#8217;re familiar with some of the core differences between Python &#038; PHP, you&#8217;ll know that Python has been &#8220;cheating&#8221; slightly.
Let [...]]]></description>
			<content:encoded><![CDATA[<p>[Note: This post is the continuation of a series. Please read <a href="http://blog.curiasolutions.com/?p=277">Round 1</a> first if you are just now joining us.]</p>
<p>In <a href="http://blog.curiasolutions.com/?p=277">Round 1</a>, PHP was looking like quite the tortoise of the group. However, if you&#8217;re familiar with some of the core differences between Python &#038; PHP, you&#8217;ll know that Python has been &#8220;cheating&#8221; slightly.</p>
<p>Let me explain: By default, Python compiles each script into bytecode on its first execution, allowing this bottleneck to be skipped on subsequent runs. PHP, however does not perform this type of optimization by default (in the 5.x line at least), so the PHP interpreter must re-compile each file every time it is run. As you can imagine, this can give PHP (without an accelerator) a huge disadvantage when compared to languages such as Python.</p>
<p><strong>With this in mind, I have decided to take Round 2 to focus solely PHP.</strong> This will hopefully provide a clear picture of the benefits of PHP bytecode caching (at least when it comes to page-views &mdash; the memory benefits are a whole other story), and give you an idea of PHP&#8217;s performance with the help of an accelerator.</strong></p>
<p>There are <a href="http://en.wikipedia.org/wiki/List_of_PHP_accelerators" target="_blank">many PHP accelerators available</a>, but I have chosen <a href="http://php.net/apc" target="_blank">APC</a> for use here (mostly due to its inclusion in the upcoming PHP 6 core).<span id="more-278"></span></p>
<h5>What you should know about Round 2:</h5>
<ol>
<li>The hardware/software platform is the same as in <a href="http://blog.curiasolutions.com/?p=277">Round 1</a>.</li>
<li>PHP has been upgraded to v5.2.9.</li>
<li>The APC tests are using APC v3.0.19.</li>
<li>ApacheBench was run with -n # -c 10, with -n usually being 5000 or 10000, depending on the test subject&#8217;s speed.</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 (minus the CMS tests, which were performed on a standard install).</li>
</ol>
<p>My apc.ini settings:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;"><span style="color: #000099;">extension</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> apc.so</span>
apc.enabled <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 1</span>
apc.shm_size <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 96</span>
apc.include_once_override <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 1</span>
apc.mmap_file_mask <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> /tmp/apc.XXXXXX</span></pre></div></div>

<p>&nbsp;</p>
<blockquote><h4>Raw PHP &#8211; <a href='http://blog.curiasolutions.com/wp-content/uploads/2009/09/php_test_src.zip'>php_test_src.zip</a></h4>
</blockquote>
<p>To investigate the speed of &#8220;raw PHP&#8221;, I created a couple of minimal PHP scripts that printed out a simple &#8220;hello world&#8221;, and read a few lines of text from a database. Take a look at the test source code for reference.</p>
<h5>APC Disabled</h5>

<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>php
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;">4199.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;
The simple 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_db<span style="color: #66cc66;">.</span>php
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2524</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">2797.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>

<h5>APC Enabled</h5>

<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>php
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;">6618.42</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;
Simple 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_db<span style="color: #66cc66;">.</span>php
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2524</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">3713.99</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>Right out of the gate, we can see that APC gives PHP a significant boost.</p>
<p>Of course, a script that simply does a &#8220;echo &#8216;hello world&#8217;&#8221; isn&#8217;t really practical, so let&#8217;s take a look at a couple of popular PHP frameworks to see what a full stack looks like.</p>
<p>&nbsp;</p>
<blockquote><h4>CakePHP v1.2.5 &#8211; <a href='http://blog.curiasolutions.com/wp-content/uploads/2009/09/cakephp_test_src.zip'>cakephp_test_src.zip</a></h4>
</blockquote>
<p>CakePHP was the slowest test subject by a large margin in <a href="http://blog.curiasolutions.com/?p=277">Round 1</a>, but if you take a look at the caching section of its core configuration file you can see that the developers have written it with acceleration in mind. It includes special configuration directives for not just APC, but also <a href="http://xcache.lighttpd.net/" target="_blank">Xcache</a> and <a href="http://www.danga.com/memcached/" target="_blank">Memcache</a>.</p>
<p>Still though, without acceleration CakePHP is a sad story indeed:</p>
<h5>APC Disabled &#8211; File Caching Engine (default)</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The return <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>hellos<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">13</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">45.25</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;
The template hello world 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<span style="color: #66cc66;">/</span>hello
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">931</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">39.90</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;
The simple database query test <span style="color: #66cc66;">&#40;</span>using the ORM<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>hellos<span style="color: #66cc66;">/</span>hello_db
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2469</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">38.80</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>However, with the help of APC things finally begin to look reasonable:</p>
<h5>APC Enabled &#8211; APC Caching Engine (in core.php)</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The return <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>hellos<span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">13</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">140.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;
The template hello world 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<span style="color: #66cc66;">/</span>hello
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">931</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">120.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;
The simple database query test <span style="color: #66cc66;">&#40;</span>using the ORM<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>hellos<span style="color: #66cc66;">/</span>hello_db
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2469</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">117.56</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, APC increases CakePHP&#8217;s speed about threefold in these examples. These results may or may not be acceptable to you (remember that we are running these tests with a concurrency of 10), but I felt much better about CakePHP after pairing it with APC.</p>
<p>&nbsp;</p>
<blockquote><h4>Kohana v3.0 &#8211; <a href='http://blog.curiasolutions.com/wp-content/uploads/2009/09/kohana3_test_src.zip'>kohana3_test_src.zip</a></h4>
</blockquote>
<p>Kohana (a divergent of CodeIgnitor) is a much more lightweight PHP framework than CakePHP, but still gives you a pretty full featureset. Since v3.0 was released shortly after <a href="http://blog.curiasolutions.com/?p=277">Round 1</a>, I decided to use the new version for the tests here in Round 2.</p>
<p>It should be noted that although file caching is enabled in a default CakePHP install, Kohana&#8217;s caching is disabled by default. I have included a couple of tests with caching disabled here to exhibit the performance of a default Kohana install.</p>
<h5>APC Disabled &#8211; Caching Disabled (default)</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The return <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;">86.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>

<h5>APC Disabled &#8211; Caching Enabled (bootstrap.php)</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The return <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;">180.50</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;
The template hello world 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<span style="color: #66cc66;">/</span>index
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">930</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">162.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>
&nbsp;
&nbsp;
The simple database query test <span style="color: #66cc66;">&#40;</span>using the Database module<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<span style="color: #66cc66;">/</span>index
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2525</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">113.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;
The simple database query test <span style="color: #66cc66;">&#40;</span>using the ORM module<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>helloorm<span style="color: #66cc66;">/</span>index
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2525</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">99.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, even without APC Kohana is quite a bit faster than CakePHP.</p>
<h5>APC Enabled &#8211; Caching Disabled</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The return <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;">125.93</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>

<h5>APC Enabled &#8211; Caching Enabled (bootstrap.php)</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">The return <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;">280.67</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;
&nbsp;
The template hello world 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<span style="color: #66cc66;">/</span>index
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">930</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">253.50</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;
The simple database query test <span style="color: #66cc66;">&#40;</span>using the Database module<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<span style="color: #66cc66;">/</span>index
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2525</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">173.28</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;
The simple database query test <span style="color: #66cc66;">&#40;</span>using the ORM module<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>helloorm<span style="color: #66cc66;">/</span>index
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">2525</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">153.90</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>Although not a threefold gain as with CakePHP, Kohana with APC+caching definitely makes a good attempt at shortening the gap seen in <a href="http://blog.curiasolutions.com/?p=277">Round 1</a> between the PHP frameworks and the offerings from other languages. Of course, if raw speed is what you&#8217;re looking for, there are <a href="http://www.doophp.com/benchmark" target="_blank">faster PHP frameworks available</a> (note that the benchmarks on that page were run on a completely different setup and should not be compared with any of the numbers here).</p>
<p>&nbsp;</p>
<p><strong>Next, let&#8217;s take a look at how APC enhances the performance of a few of PHP&#8217;s heavyweights.</strong></p>
<p>&nbsp;</p>
<blockquote><h4>WordPress v2.8.4 (default install)</h4>
</blockquote>
<p>Although I&#8217;ve heard that WordPress has a built-in caching setting, a quick glance at wp-settings.php did not reveal anything. So, there are simply two WordPress tests&mdash;with APC, and without:</p>
<h5>APC Disabled</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">5519</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">24.80</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>

<h5>APC Enabled</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Document Path<span style="color: #66cc66;">:</span>          <span style="color: #66cc66;">/</span>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">5519</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">74.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>&nbsp;</p>
<blockquote><h4>Joomla v1.5.14 (default install, without sample data)</h4>
</blockquote>
<p>The results of these tests were quite disappointing to me, and made me wonder if I was doing something wrong. Sadly, it looks as though Joomla is quite the slow one of the bunch.</p>
<h5>APC Disabled</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Joomla Caching Disabled <span style="color: #66cc66;">&#40;</span>default<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>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">4006</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">27.90</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;
Joomla Caching Enabled <span style="color: #66cc66;">&#40;</span>File<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>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">4006</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">31.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>

<h5>APC Enabled</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Joomla Caching Disabled<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;">4006</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">41.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>
&nbsp;
&nbsp;
Joomla Caching Enabled <span style="color: #66cc66;">&#40;</span>APC<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>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">4006</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">45.01</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>Drupal v6.14 (default install, clean URLs disabled)</h4>
</blockquote>
<p>Drupal has several caching settings, so I decided to see what each one would look like and how much of a difference &#8220;aggressive&#8221; caching made.</p>
<h5>APC Disabled</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Drupal Caching Disabled <span style="color: #66cc66;">&#40;</span>default<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>
Document Length<span style="color: #66cc66;">:</span>        <span style="color: #cc66cc;">5548</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">36.72</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;
<span style="color: #ff0000;">&quot;Normal&quot;</span> Drupal Caching<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;">5548</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">289.69</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;
<span style="color: #ff0000;">&quot;Aggressive&quot;</span> Drupal Caching<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;">5548</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">335.68</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>

<h5>APC Enabled</h5>

<div class="wp_syntax"><div class="code"><pre class="progress" style="font-family:monospace;">Drupal Caching Disabled<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;">5548</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">83.93</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;
<span style="color: #ff0000;">&quot;Normal&quot;</span> Drupal Caching<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;">5548</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">498.37</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;
<span style="color: #ff0000;">&quot;Aggressive&quot;</span> Drupal Caching<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;">5548</span> bytes
Requests per second<span style="color: #66cc66;">:</span>    <span style="color: #cc66cc;">564.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></pre></div></div>

<p>As you can see, Drupal&#8217;s caching (especially when combined with APC) changes things drastically. These results seem to indicate that Drupal&#8217;s caching does a great job of allowing the CMS to get out of the way.</p>
<p>&nbsp;</p>
<h4>Closing thoughts</h4>
<ul>
<li>The benefits of a PHP accelerator are really too good to pass up. Even without written-in caching, an accelerator can give your code a significant boost.</li>
<li>While these tests have only really explored the impact on website page-load times, a PHP accelerator typically also cuts down on the amount of memory used by your PHP scripts.</li>
<li>PHP 6 has promised to fix a lot of things, including the lack of built-in bytecode caching. It will be interesting to revisit these tests in a few years (?) to see how much optimization the new version brings to the table.</li>
</ul>
<p>&nbsp;</p>
<h5>Can&#8217;t get enough of this madness? Just wait until you read <a href="http://blog.curiasolutions.com/?p=409">Round 3</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-technology-shootout-round-2-php-deserves-a-helping-hand/feed/</wfw:commentRss>
		<slash:comments>1</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>
