I'm attending ZendCon today and giving a demo in the keynote presentation by Andi Gutmans, one of the creators of PHP, and co-founder of Zend. I'm psyched to show off IIS7 and PHP along-side Andi!
I only have 5 mins to demo, so I decided to focus the demo on two things: 1) how easy it is to get PHP up and running and 2) the early results of our collaboration on performance for PHP on Windows.
Throughout the demo I'll be using Qdig, a simple, but powerful image gallery application. Setup of Qdig is really easy. To use the thumbnails and image resize features of Qdig, make sure you've enabled the GD library in your php.ini file. Download the zip file, unzip it to C:\inetpub\qdig, grab some of your favorite images and place them in a subdirectory, then - as described in the install.txt file - allow IUSR and NetworkService full control of the qdig-files directory, browse to the site once, then re-set permissions back to read/execute.
Part of this demo is measuring the performance gains we've made. To simulate load on the application, I'll be using an application called 'WCat', short for Web Capacity Analysis tool. It is a VERY powerful tool, and we'll only be scratching the surface of what it can do. The version of WCat that I'm using is in the IIS6 resource kit. There are some cool tools in there, and while they haven't been tested on IIS7, most of them do work. Once you've downloaded the resource kit, and installed it, proceed to the next step.
I've setup a simple wcat script to test my QDig performance. You can download the zip file with .bat and configuration scripts here. Unzip to C:\demo\performance and check out the contents. ThomaD gave me these a while back, and I've been tweaking them ever since. startStress.bat will launch both the controller, and the client, which will pound the URLs found in php_script.cfg for about 10 seconds. You'll see a quick summary of the results after the test has run.
I wanted to do something useful with Windows Sidebar during the demo, so I created my very first gadget last weekend, which you can download from the Gadget Gallery site. It launches perfmon, or any other configured path (I configure mine to launch my c:\demo\performance\perfmon.msc file, which has the get requests/sec perf counter).
Installing PHP on IIS7
The first part of the demo follows the steps of my previous blog post, and is really straight forward. The steps are described in this post titled: How to install PHP on IIS7 (RC1). Once I've got PHP installed, I run my performance test using that fancy gadget and get the following results:
PHP.net download performance using ISAPI (fast, but unreliable) - (full size image)
As you can see, I'm getting a little over 60 requests per second. This is about as fast as PHP can go today, using the community distribution of PHP from http://www.php.net/. ISAPI runs PHP inside the IIS worker process on multiple threads, making it similar to ASP or ASP.NET. Unfortunately, since some PHP extensions aren't yet threadsafe, running it in this way usually leads to crashes.
Installing IIS7' FastCGI module & PHP
As a result of the collaboration between Microsoft and Zend, there is now a faster and more reliable way to run PHP. The first step is to download the new IIS FastCGI feature, available as a Technical Preview release on this page of the IIS.net site. Download and unzip it to c:\fastCGI.
The next step is to download PHP itself. You can, of course, use the IIS FastCGI feature with the community distribution of PHP which we downloaded for the first demo. If you want the latest PHP core engine performance enhancements from Zend, you can also download a Technical Preview here. This zip file contains a special build of PHP for this Technical Preview, and is for experimental use only. Please don't ask Zend for support. I unzipped my copy to C:\zendPHP.
I should also mention that if you want to try Zend's Core product, which contains Zend's fastCGI implementation as well as some other cool features and tools, you can download from Zend. Zend's products are eligible for full support, and are truly Enterprise-class software. We plan to work with Zend in the future to enable Microsoft's FastCGI feature to integrate closer with Zend's products.
Once you've unpacked both the fastCGI module, as well as the PHP distribution you're ready to use, run the fastCGI installer like this:
Install FastCGI and register PHP handler (full size image)
Now that you've got the FAST version of CGI installed, and the handler re-mapped, run our performance benchmark again and see the results (shown side-by-side the previous run for comparison):
FastCGI performance rocking! (full size image)
Wow! Despite the fact that Microsoft and Zend just started working together, the results look very, very good. The FastCGI + Zend PHP numbers for Qdig, on my laptop, are almost twice what I get from today's PHP. And don't forget, Zend has committed to submit the performance enhancements back to the PHP community, so they will be showing up soon in the usual PHP.net distributions.
In addition to the great performance, the FastCGI method of running PHP should be significantly more stable than the ISAPI method. This is because with FastCGI, PHP is still running single-threaded in one or more processes in the FastCGI pool.
IIS Kernel Mode Caching for PHP applications
Of course, this is just the start for PHP developers. Once they're on Windows and IIS7, there are a ton of cool features to begin taking advantage of like distributed configuration, a sexy new admin tool for IIS configuration, diagnostic tools like failed request tracing, .NET integration (think ASP.net forms auth for a PHP app!) and more - all of which are unique to IIS7. One of the cool things that I wanted to show off, while we're talking about performance, is the new output cache.
The IIS7 output cache is a new feature in IIS7 which makes it possible to cache entire responses in memory - even from dynamic content. Unlike the existing caches IIS has, it is a 'smart' cache, enabling you to configure it to cache separate copies of responses for the same page (like index.php) based on query string value, so it works great for the Qdig application we've been using. One of the other really cool things about it is the fact that it is integrated with the http.sys (kernel mode driver) cache, allowing for blazing fast performance. Output caching is going to be a very powerful feature for all kinds of applications, from PHP to ColdFusion, Classic ASP to CGI. It will work with any content type, and can significantly speed up performance for applications where the underlying data doesn't change (like our image gallery), or where the changes occur at a predictable rate (so you can timeout the cache at the expected interval). Even in cases where the data is changing, say, once a second, it may make great sense to use the output cache with an expiration of 1 second. This allows for the dynamic processing to occur only once a second, instead of on every request, significantly speeding up response times and lowering CPU.
To configure output caching for QDig's index.php page, we first need to "unlock" the <caching> configuration section. Open \windows\system32\inetsrv\config\applicationhost.config file and search for <caching>. Cut it from it's current location, then search for (<location path="" - without parenthesis) and paste the caching configuration section in below it like this:
<location path="" overrideMode="Allow">
<caching enabled="true" enableKernelCache="true" />
The point here is to move it under the section of applicationhost.config that is marked as overrideMode="Allow", which enables it to be set at the application level.
Now that you've unlocked it, create a web.config in your QDig directory, and paste in the following configuration:
<add extension=".php" location="Any" kernelCachePolicy="CacheUntilChange" varyByQueryString="Qwd,Qif,Qiv,Qis" />
Now that you've got kernel caching configured, run the performance test again. Before you do that, you may want to change the scale of your perfmon chart from (0..100) to (0.8,000). :) Here is what I get with kernel caching enabled:
Kernel Mode Caching PHP responses @ 6000 requests per second! (full size image)
To be honest, I'd expect it to be even faster. It would normally be in the 10s of thousands. The main reason it isn't is that I'm running the client and server on the same box, and any client generating 6000 RPS is going to use quite a bit of CPU, limiting the time slice kernel has to use. But going from 100+ RPS to 6000RPS isn't to shabby, eh?
One of the cool things in Vista is a new command line tool that will show you what is in the http.sys cache. Run "netsh http show cache" to get a snapshot:
NetSh cmd-line tool showing http.sys cache (full size image)
IIS' new FastCGI feature is going to be a huge benefit for web application frameworks like PHP which expect single-threaded environments. It lets them run fast and reliably on Windows, and begin take advantage of all the cool features of IIS. Using it, along with Zend's PHP enhancements in this demo almost doubled QDig performance on my machine, and made it much more stable.
To make sure anyone can take advantage of FastCGI on all of our existing platforms, we've built an ISAPI version of it that can run on Windows XP and Windows 2003 (IIS 5.1 and IIS 6.0) as well as a new module version for IIS 7.0. Check out the IIS FastCGI page for more information. Technorati Profile