ZendFramework performance

Comments

[this is good]
Reading
Last comment didn't survive registration :)

It said that anyone else reading this should immediately bookmark the blog entry for future reference - I can't remember another single example which summarised these performance pointers quite so clearly or simply. Nicely done!
[this is good]
One remark: you use include_once in your __autoload. But since __autoload is only called whenever the class defenition hasn't been loaded before, you could use require or include. As Rasmus pointed out, *_once should be avoided.
White on black hurts my eyes very hard. What about making the bg for main content white and use a dark color for text?
[this is good]
Interesting list, but not quite sure by what you mean by this: "Adjust PHP's realpath.cache setting and .ttl"

There are a couple of ways to take this, so I'm going to take you literally and provide you another thing to experiment with:

Once can significantly improve the speed of one's autoloader functions by caching the full (realpath()) of the included files and building a mapping between Class/Interface names at run-time.
Hmm... My post got truncated... here's the rest of the masterpiece that I can remember... :)

All subsequent page renders just use the mapping instead of executing through the "native" autoload functions. This short cuts a lot of decision making and reduces the overall include count.

We measured a ~12% speedup for a 4 deep include path, stat on and ~25 includes per page render. It's most effective if you use the realpath() instead of a relative one. We're using this approach with production code with both the Zend Framework and ezComponents. YMMV.

Some caveats:

1. No executable code in the class/include file. (All code in class/functions...)

2. No order of operation requirements. (Not typically an issue if #1 holds true.)

3. One to one mapping between autoload names & included files. (This performance optimization won't work in the general case of business rules logic being used to change which file to include based on autoload parameters + current run state.)

It's 40-ish lines of code to write...

One remark: you use include_once in your __autoload. But since __autoload is only called whenever the class defenition hasn't been loaded before, you could use require or include.

Interesting, I had thought about that, but only briefly. I profile the improvements. :-) Thanks for stopping by!

Interesting list, but not quite sure by what you mean by this: "Adjust PHP's realpath.cache setting and .ttl"

I just meant to up the cache and ttl, according to what you need. The default is 28k or so. I am not sure though if this really helps, I tried too many things in the process without benchmarking each step.


There are a couple of ways to take this, so I'm going to take you literally and provide you another thing to experiment with:

Once can significantly improve the speed of one's autoloader functions by caching the full (realpath()) of the included files and building a mapping between Class/Interface names at run-time.

That's actually on my list, but somehow I did doubt that building a table in userland is faster than what APC can provide. ;-)

Sorry about the issues with the commenting and so on. Up until now, I was too lazy to run my own blog somewhere but I'll think about it.

Last comment didn't survive registration :)

Sorry about that and thanks for stopping by. It's good that you didn't drop off the map completely. :-)

White on black hurts my eyes very hard.

Hehe... I just switched it to something more eye-friendly. So I hope! How do you like the current one? :-)
How do you like the current one? :-)
Yes, I like it!! :-)
Good article :)

Also, you might want to disable Zend_Controller_Action_Helper_ViewRenderer, another performance killer hidden inside the Zend_Controller package: 22% Drop in Responsiveness

Fed
Just for fun I clocked the impact of realpath vs. using an APC-based straight mapping autoloader per my previous suggestion. pages/sec from a relatively low-end dev box:

No APC-autoloader, no realpath = 2.94 p/s
No APC-autoloader, realpath (16k, 120ttl - default php.ini) = 2.95 p/s
APC-autoloader, no realpath = 3.23 p/s
APC-autoloarder, realpath (16k, 120ttl) = 3.36 p/s

As always, YMMV and note those are dev box, not server-iron, numbers...

Oh, and yes, I was very surprised by this result, but it appears completely skipping the Zend & ezc autoloader implementations is a good thing...


In case anyone is interested, the autoloader issue is discussed here in more detail: Performance Requiring the Autoloader

Fed

22% Drop in Responsiveness

OK, it seems that I have fell victim to my own blog. I thought I replied to you already but I didn't see my comment.

Anyway, I couldn't see that improvement, in fact my app loaded slower when I had to initView() and $this->render() myself. Any idea why that would be the case? I am using the 1.6.3 (?) release of the Zend Framework.

Btw, for those who care, my autoloader uses a regular "include" now (which makes a lot of sense), I also managed to gain more performance from a couple Zend_Loader improvements, because I still use my extension to load controllers and models.

I will post about all of them next week (if I manage to reconstruct all with cachegrind.out.* and svn log ;-)).
[this is good]
Your apache + nginx setup pretty interesting. You seem to use NGINX what most people use Squid for.. I'm wondering if there's any good benchmarks between the two (and otherwise I might want to get on that :P )
Indeed I do.

I must admit that I have only little experience running Squid as a proxy and cache for a network in a SO/HO type of environment.

But I'm almost sure that nginx will outperform Squid in this case since it's very lightweight and optimized to loadbalance and proxy. Feel free to run benchmarks though and let me know how they turn out. :-)
>> ... our Apache does not log - why load mod_config_log ...

How do you log the request for stats instead?
We use Google Analytics. Which is not perfect, but it works.
If you care about performance in a whole (server side and client side) I would reconsider my choice for Google Analytics. It often slows so much down that I disabled it in my hosts file. :P

If you care about performance in a whole (server side and client side) I would reconsider my choice for Google Analytics

Well, I see that and I know we are not tracking people with JavaScript disabled, or an ad blocker, etc.. But it doesn't really matter in our space. Also, take into account that processing logs from three servers requires resources as well since you need to combine/merge them and then analyze them.

Last but not least, the stats Google Analytics provides are very comprehensive and while they are of course not un-matched by free solutions (e.g. Awstats probably offers the same), a better solution would also require an investment. And they are not cheap.

So far it's been a matter of resources for us. Both time and money.

If you have an easy-to-use-solution, let me know. We are always evaluating. :-)
[this is good]
Very nice post :)

Just one question from my side. How did you get managed to store results returned by Zend_Db_Table (i mean the magic methods like find*, etc..) in cache? These are full blown object-graphs with an active database link. These objects can't be reconnected to DB after serializing and unserializing as far as I know..
Can you explain what you mean exactly?

What we cache is the table definition for the module so the table info is not regenerated on each requests. The table structure itself changes rarely, if ever so that cache has a huge TTL.

Aside from that we are not caching so many database queries, primarily because the data is ever chenging anyway. There is one where we cache and as I outlined I cache using apt_store/apc_fetch.

In general, if I were to implement a cache on larger sets, I'd use memcached to do it. It just requires a little thinking before we implement it because we need to destroy the cache when data gets updated so people see their edits/changes instantly and don't have to wait for the cache to expire. I'm sure there are solutions in and outside of the Zend Framework to do that.

Also, I would probably cache results - not the full blown object.
Well, if you use the methods built-in to Zend_Db-Table (like find() oder fetchAll you get a full-blown Zend_Db_Table_Rowset object back, which is collection of Zend_Db_Table_Row objects or there derivates.The problem is you can't serialize and unserialize these objects, because after serializing, they are no more connected to database and ZF throws an error.

A logical solution is to use -
I'm not really using find(), sometimes fetch*(). Most of those convenient methods are expensive, that is true.

If I'd cache anything there it would be the pure resultset, not the entire object.
Any test done on
- compiling by hand the lamp stack instead of using distro packages
- disabling registration of file access time on the filesystem hosting the website
or other os-level tuning?

Also more details about setting up nginx as reverse proxy would be great...
Hey,

my software is compiled - thanks to Freebsd ports. I don't use any packages (except for cvsup, and that's sort of unrelated to the rest of the setup). The apache13 and mysql ports allow me to pass a couple flags in, so for example I do disable features I do not want/need etc.. Aside from those, I also build our own Makefile(s) when necessary.

As for OS-level performance tuning, I've applied some things from tuning(7) on my servers, but that could be improved (probably).

I'll follow-up with an nginx post when I have a new blog (later). But the setup is really trivial.

Till
[this is good]
You use Zend_View_Heler_Action in project ?
We did in the beginning but stopped using it due to the poor performance. IMHO, executing an action from a view is a hack anyway, so why not assemble the data beforehand? :-)
[this is good]
[this is good]

Post a comment

Already a Vox member? Sign in