Zend Framework Performance Zend_Loader

by Mike Willbanks on December 23rd, 2007

This post is related to the last post on PHP Accelerators and utilizing the Zend Framework. I changed out the Zend_Loader::loadClass() implementation that I was utilizing to load all of the classes and found that it drastically slowed things down. I am not just talking slightly, but a massive change in performance.

In the previous post APC was the fastest with 900 requests. After taking the Zend_Loader out of the picture in the bootstraps and moved them to a require_once function (I attempted just simply require, but that caused some issues likely due to some conflicts with the Zend Framework requiring their own files already in specific instances.

Results

The APC requests went from 914 to 27,411 with the same ab bench.

Concurrency Level:      10
Time taken for tests:   60.3722 seconds
Complete requests:      27411
Failed requests:        0
Write errors:           0
Total transferred:      5976688 bytes
HTML transferred:       0 bytes
Requests per second:    456.82 [#/sec] (mean)
Time per request:       21.890 [ms] (mean)
Time per request:       2.189 [ms] (mean, across all concurrent requests)
Transfer rate:          97.26 [Kbytes/sec] received

If you don’t know it by now, just for clarity, DO NOT USE Zend_Loader in your applications unless you would like to see it drastically slow down.

From PHP

12 Comments
  1. We’re considering which bytecode cache to use (Xcache or APC). Did you notice any improvements with require_once and Xcache?

    Besides, if using a bytecode cache wouldn’t it make sense to create a single include file with all the required classes (or at least the most commonly used ones)?

  2. This is do to 2 things

    1. All the checks they do within Zend_Loader to “validate” a file before loading it.

    2. BUT the biggest is APC… When using ANY Dynamic class loader APC can’t cache those files fully as its not sure which files will load on any single request. By hard loading the files APC can cache them in full.

  3. Andi Gutmans permalink

    Are these results with Zend Framework 1.0.3? Can you please send me the scripts you tested and the results of both with and without ZF? We’ve been looking at optimizing Zend_Loader and already have some nice improvements in 1.0.3 and more to come.

  4. Kaloyan K. Tsvetkov permalink

    That’s really interesting. Can you publish the results using the other optimizers too ?

    I can only assume that when using Zend_Loader in the __autoload “routine” we are still going to see such nasty results, right ?

  5. @DrSlump
    1. I am going to retest sometime tonight with all of the different caches in 3 different ways:
    a. Zend_Loader
    b. require_once
    c. require

    @Richard
    1. I agree, I was looking at all of those and could see the slow down since it does so much checking. Most likely best if we could flag those checks off :)
    2. APC worked fairly well with require_once over the Zend_Loader but I am going to retry with require.

    @Andi
    If you look at the other post, you will see the files. The difference was simply with using the Zend_Loader and not using the Zend_Loader.

    @Kaloyan
    1. I will be re-running the tests tonight: both with the Zend_Loader, require_once and require.
    2. The loader doesn’t exactly use __autoload but explodes the string apart and starts to look for it in the path.

  6. Kaloyan K. Tsvetkov permalink

    What I meant is that sometimes the Zend_Loader is used to autoload classes, because using prefixed pseudo-namespaces is the usual approach in ZF based applications: this makes the development process a bit quicker since instead of explicitly loading a class — like Zend_Loader::loadClass(‘Mike_Models_User’) — you can just instantiate the class and the autoload will call Zend_Loader for you. This is the scenario I was talking about. I expect it to be even slower than just using Zend_Loader::loadClass() because of the extra “autoloading” call, but nevertheless it will be interesting to see results.

  7. In an application like yours, Zend_Loader causes _hundreds_ of additional stat calls. If you’re using APC, and set apc.stat=0 [you did that for your test, right? ;) ], you would essentially go down to 0 stat calls instead of the hundreds of stat calls.

    If you have:
    require “composed_$var”

    APC _will_ need to stat everytime. With hard-coded strings (relative paths are okay) – you would save that stat call (usually more than one though). Zend_Loader not only gets a hit on this, but it in fact does its own ‘checks’ to make sure the file exists. Meaning, even more stat calls (and other stuff).

  8. @daaku
    I left the APC configuration defaulted when I did the original tests. I wanted to get a real world picture of what (most) people do as we know a lot of areas where it is simply just installed but not configured for tuning. I am more than likely going to do a separate test case where I try out a few different configurations, however, for the main test I am going to simply use the defaults and then whatever is faster. Next I will likely post about tuning APC after checking different configurations against the application in the same way.

  9. – BUT the biggest is APC… When using ANY Dynamic class loader APC can’t cache those files fully as its not sure which files will load on any single request. By hard loading the files APC can cache them in full. –

    /nod. This is actually why you should say *away* from Zend_Loader. I think we need to add in some conditionals within the documents explaining that Zend_Loader does /not/ play with APC (not just “not well” but not at all). I’ve always used hard coded require statements because of this.

  10. Mike — a few things: First, you should have some sort of contact form or address on your site; I wanted to ping you about my next two comments; if you can, email me at ‘matthew’ at zend.

    Next, can you re-run your tests with a more recent version of ZF? We made some changes to Zend_Loader to optimize it slightly — primarily, we removed the call to isReadable() prior to loading a class file; this removes one stat call, which makes a pretty significant difference in Zend_Loader’s performance as an autoloader. Our internal tests show that at this point, Zend_Loader tends to perform within a few percentage points of a straight require_once.

    Third, would it be possible for you to publish the code you used to test, as well as the specs of the environments you tested in (OS, PHP version, php.ini settings, ZF version, etc.)? It’s hard to take these numbers credibly when nobody can independently verify them.

    Thanks!

Trackbacks & Pingbacks

  1. klog » Blog Archive » popularity of php vs java
  2. Generation 5 » An Awesome Autoloader for PHP

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS