Zend Framework 1.7.2 is a cool PHP framework for developing MVC-style applications. It's just very slow. I'm talking about the time it takes just to execute the bootstrap code, before even reaching your application code.

The slowness seems to be caused by the large number of Zend_xxx classes, which are all located in separate PHP include files. At the beginning of every HTTP request, dozens of classes must be included and instantiated. You don't even see most of it, because Zend Framework includes them automatically.

Zend has official performance advice telling you to optimize the include path, strip away require_once calls and use Zend_Loader and PluginLoader. On my test server (4-core Xeon 3.40GHz, 2GB, Apache 2.2.11, PHP 5.2.8, APC 3.1.2, ZF 1.7.2), this gives 220 requests/sec for a hello world app. The app uses a controller, a view and a layout just to output 'hello world'. It has the auto-view-renderer and layout inflector disabled, so it manually calls setLayout() and render().

To make it faster, I wrote my own class autoloader and logged each include file that was needed for the application. Then I concatenated all the 40 include files in the correct order into one mega-include (340 kb). This way I got 390 requests/sec, which is 77% performance increase.

For the last step, I wrote some very experimental PHP code to serialize and cache the Zend_Controller_Front object and some other objects, which are always created exactly the same way in the beginning of each request. In addition to serializing the objects, I also had to separately store all static class variables, which Zend Framework uses quite extensively. This way I reached 410 requests/sec, which is about 86% performance increase compared to the original version.

In conclusion, it seems to be possible to get fair performance out of Zend Framework, but everything must be tweaked. It's probably possible to take the object caching approach even further, by serializing and caching Zend_View/Zend_Layout objects and all their little helper classes. More challenging are all database-related objects, which cannot be serialized because they have an active database connection.

I really wish PHP had some way to freeze a set of classes and objects, which would always be already in memory in the beginning of each request. That is what I now try to simulate using serialization and APC.

Published 10.1.2009