<?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>Streaky's Blog &#187; prepared statements</title>
	<atom:link href="http://mybrokenlogic.com/tag/prepared-statements/feed/" rel="self" type="application/rss+xml" />
	<link>http://mybrokenlogic.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Mon, 19 Jul 2010 21:50:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>A Persistant PHP Application Server</title>
		<link>http://mybrokenlogic.com/2009/02/18/a-persistant-php-app-server/</link>
		<comments>http://mybrokenlogic.com/2009/02/18/a-persistant-php-app-server/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 09:37:19 +0000</pubDate>
		<dc:creator>streaky</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[application server]]></category>
		<category><![CDATA[prepared statements]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://mybrokenlogic.com/?p=3</guid>
		<description><![CDATA[What I really wanted to talk about is an application server that I wrote for PHP.  The problem I identified a while back is when I&#8217;m writing code in PHP the thing I&#8217;m doing most of the time is writing web applications. Now PHP is usually fast, at least that is, when you&#8217;re not writing [...]]]></description>
			<content:encoded><![CDATA[<p>What I really wanted to talk about is an application server that I wrote for <a href="http://en.wikipedia.org/wiki/PHP" target="_blank">PHP</a>.  The problem I identified a while back is when I&#8217;m writing code in PHP the thing I&#8217;m doing most of the time is writing web applications. Now PHP is usually fast, at least that is, when you&#8217;re not writing huge sites that take a lot of requests. The way PHP is normally, historically, implemented is for every page request you have to build up and tear down your application, and with some SAPIs you have to also build up and tear down the PHP binary on top.</p>
<p>That presents a problem for performance, in that every time somebody requests a page you&#8217;re doing a lot of work to get the application to a state where it can start spitting out content &#8211; then at the end throwing away all that hard work you did. It wastes physical time and CPU cycles, not forgetting often IO and memory in the process. To resolve the issue you have to make your application persistent, which is something that PHP isn&#8217;t designed for in this context.<span id="more-3"></span></p>
<p>A while back I discovered that somebody wrote an <a href="http://code.google.com/p/appserver-in-php/" target="_blank">SCGI handler in PHP</a> &#8211; so that you can write your application in a way that you build it up and it serves requests from it&#8217;s already-running state, your HTTP server talks to your application via the SCGI class and dumps this output back to the HTTP server and handles the next request without it all being torn down. That&#8217;s useful, it&#8217;s what you want when you&#8217;re serving huge numbers of requests in short spaces of my time. The problem is this isn&#8217;t a complete answer to the issue.</p>
<p>Firstly the code can only handle 1 request at a time. If a concurrent request comes in it&#8217;ll get queued by the HTTP server until the previous request has finished. This is easy enough to resolve &#8211; if your HTTP server supports it you can just spawn multiple instances and make it round-robin the backends. Another problem is these different processes don&#8217;t know about each other, they&#8217;re completely dumb to the fact that there are more versions of themselves running &#8211; they can&#8217;t share data with their siblings, and if you want to have a process to watch over them and make sure everything is fine you need to write that code separately. Then you get even more problems if your traffic gets to the point where it&#8217;s too much for the number of processes you have spawned; you need to manually increase the number of processes.</p>
<p>I decided I needed to come up with a solution to the problem.</p>
<p>First on my agenda was to ensure it spoke a language that most if not all HTTP servers understand. SCGI is pretty well supported, but not by everything. FCGI uses a complex binary communications protocol, which is a good protocol and it&#8217;s well supported &#8211; the problem is when you&#8217;re attacking a problem like this you have no idea if in the end your solution is going to improve things at all &#8211; so it&#8217;s potentially a complete waste of time trying to implement a protocol if the project fails.</p>
<p>I settled with making the server code support HTTP, which aside from the fact it&#8217;s well supported, has other fringe benefits. Firstly you can point a browser at the application and test the code directly with no HTTPD needed, which creates all sorts of opportunities for doing fun things when debugging, not least because you can find out if your problem is caused by your code or the HTTP server. You can also stick hardware load balancers in between your frontend HTTP server and backend slave application servers if you need that kind of capacity. HTTP load balancers are easy to get hold of. You can even put squid between the app server backend(s) and the frontend HTTP server if you need to without making <em>any</em> changes to your code if you need to. Now bear in mind this is was never intended to be exposed to browsers directly, just you can because it speaks HTTP 1.1 &#8211; but it&#8217;s not the idea. This is not a HTTP server in it&#8217;s own right, not even close., it isn&#8217;t intended to be used this way. This is not <a href="http://nanoweb.si.kz/" target="_blank">Nanoweb</a>.</p>
<p>The next step is was to resolve the 1 connection at a time issue. Unfortunately PHP doesn&#8217;t support threads in any kind of way, shape or form. It&#8217;s not the end of the world, but despite there being a PECL extension covering threads this isn&#8217;t going to work, it hasn&#8217;t been updated in years &#8211; and even when it was updated it never gone finished, which is a huge shame. Hopefully one day somebody recovers that extension because it has huge potential outside the traditional &#8220;PHP does this and only this&#8221; worldview.</p>
<p>The only opportunity for doing this stuff in PHP is to use pcntl_fork(), so I hacked in some forking code. Experience teaches me that it&#8217;s not sensible to fork our server on every request &#8211; you have to fork enough children to handle your load up-front. What I was left with after a few hours was a HTTP server class that is extended extend by your application class, in a similar way to the application server I found previously &#8211; you write a constructor that builds up stuff you always need, maybe a template engine, read in some data files, connect to a DB and whatever, then it returns to the server class which forks the process into a bunch of children. When a request comes in i hits one of the children which processes the HTTP headers and body (if it&#8217;s a POST), which in turn passes the request off to your code.</p>
<p>After bashing it with ab it was clearly very fast, stable and working well. The result was a fully-functioning web application (a rebuild of paste2.org) spitting out it&#8217;s home page in about 0.0004s on my crappy local development server. For the sake of unscientific comparison, the &#8216;same&#8217; code on paste2&#8242;s production server manages to spit out the same page in about 0.01s. That&#8217;s a pretty major time improvement, on significantly worse hardware.</p>
<p>It has a few issues still else I&#8217;d be putting the code up for people to look at &#8211; they&#8217;re all solvable though with a bit of time which I don&#8217;t really have right now. The first is some of the code is a mess as it is. The second one is if MySQL (or more accurately, I&#8217;m using PDO right now, hence whatever you use) goes away the code isn&#8217;t aware and tries to keep banging away at the old connection/prepared statement &#8211; but that&#8217;s going to be easy to resolve. The next issue is I haven&#8217;t added any kind of communication between processes yet but that&#8217;s just a matter of getting to it, and the code doesn&#8217;t need it &#8211; it will just add more reasons to use it. Basically right now it&#8217;s not even as cool as it could be.</p>
<p>Another problem is that no opcode cacher for PHP supports CLI as far as I can see, not because of technical difficulties but that they, I guess, have been completely useless in the past. The reason why this would be useful is that some template engines (including mine) repeatedly try to include the same file which it seems isn&#8217;t cached anywhere. That could be speeded up by an opcode cacher. I could use the CGI SAPI or patch <a href="http://xcache.lighttpd.net/" target="_blank">XCache</a> and give it a try, and then see what happens. [<strong><em>Update</em></strong>: I tried this with APC in CGI SAPI instead of CLI and it does improve things, but with the nature of the beast <em>milage may vary</em>].</p>
<p>The last issue I can think of is that I haven&#8217;t written in a way yet for the code to monitor itself and spawn new children when it gets clogged up or kill off children when it has too many. It does spawn new children when another dies though, that is to say it ensures there&#8217;s always x children spawned.</p>
<p>Because the app is persistent there&#8217;s some other fringe benefits that one might not usually think about.</p>
<p>Around the time I was hacking this together, in ##php on Freenode, Rasmus was complaining about how there&#8217;s no cache for prepared statements in MySQL. A few hours later it occurred to me that because what I&#8217;ve been doing is persistent across requests and that it holds open connections to the database server if you make your app work that way (and you want it to work that way) it&#8217;d be possible to implement something resembling a prepared statement &#8216;cache&#8217;. I should say before I get slapped around for what follows &#8211; I know what I&#8217;m about to describe isn&#8217;t <em>actually</em> a cache but it&#8217;s the next-best thing.</p>
<p>I pulled out the application-specific PDO code from my test application (the paste2.org rebuild), and moved it to the main app server parent class. Then I added two methods, one creates a prepared statement from a string and an identifier string (whatever you like as long as it works as a PHP array key) and stores it, the other returns a reference to the &#8216;named&#8217; prepared statement. Essentially you can now add prepared statements in your app&#8217;s constructor (or wherever, realistically) and reuse them time-after-time-after-time.</p>
]]></content:encoded>
			<wfw:commentRss>http://mybrokenlogic.com/2009/02/18/a-persistant-php-app-server/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
