Optimising the Zend Framework
Asked Answered
T

5

7

I'm trying to get as much performance as I can out of my application, which uses the Zend Framework.

I'm considering using the Zend Server, with APC enabled. However, I need to know a few things first.

Is there any benefit of using Zend Server + Zend Framework, or should I just use any ordinary system to host this?

Shamil

Thibeault answered 16/1, 2011 at 23:16 Comment(5)
Small clarification, Zend Server [zend.com/en/products/server/] is not a system, its an enterprise application that runs on a physical server in a *nix environment. As a developer I love Zend Server especially when you can debug on production.Jauch
Hi, I should have not said system. Wrong word, completely. By system, it meant, an ordinary LAMP stack.Thibeault
it not LAMP :D It's just the AMP part. It can be WindowsAMP or LinuxAMP ;)Brecher
I'm using this on a Linux Server, so in this case, it is LAMP. I still like WAMP and WIMP though :)Thibeault
Also see Using Zend Framework for highload projectsRainwater
F
26

My tips for faster ZF (try from top to bottom):

Optimize include path

  • zend path first
  • models next
  • rest at the end

Use PHP 5.5 with OPCache enabled [NEW]

  • I can't stress this enough
  • gains around 50%

Cache table metadata

  • should be cached even if no other caching is needed
  • one of our application performance improved by ~30% on Oracle server ;)

Favour viewHelpers over using action() view helper

  • create view helper that access your model
  • or pass only the data from model and format them with view helpers

Use classmap autoloader

  • since ZF1.11
  • preferably with stripped require_once calls

Minimize path stacks

  • there are a lot of path stacks in ZF
    • form elements
    • view helpers
    • action helpers
  • each path stack lookup means stat call = performance loss
  • default classes are more and more expensive with every path on stack

Strip require_once

  • strip require_once from Zend's classes in favour of autoloading using find & sed

Favour render() over partial() view helper

  • no new view instance is created
  • you need to set variables outside the rendered view scope, inside the main view!
  • you can also replace partialLoop() with foreach + render()

Cache anything possible

  • small chunks that require lot of work and change seldomly (like dynamic menus)
  • use profiler to find low-hanging fruit
    • what you think is slow may not really be so slow
  • cache everything that can have cache set statically
    • see manual - Zend_Locale::setCache(), Zend_Currency::setCache(), Zend_Db_Table::setDefaultMetadataCache(), configs...

Never use view helper action() or action helper actionStack()

  • Never use them unless 100% needed - for example for complicated data output, but mind the performance loss they pose
  • They create whole new dispatch loop and are performance killers!

Disable viewRenderer

Try my superlimunal plugin

  • it merges included classes to one long file to minimize stat calls
  • get if from GitHub
  • measure performance gain

Server-side file minification

  • It makes sense for really big files - HDD is always the bottleneck
  • Even micro-optimization works fine sometimes
    • classmap with all ZF classes' paths is HUGE, striping whitespace and replacing long variables with $a and $b brought performance gain when having "dry" opcode cache and HDD under pressure.

Any opcode cache is of course a must have ;) (APC, ZendOptimizer, etc.)

Franklyn answered 17/1, 2011 at 21:55 Comment(13)
I'm unconvinced of the require_once stripping tbh. It's never shown a great improvement in my benchmarks. Probably because it's fairly good at only pulling in classes just before they're needed. I dont suppose you have any links on this being a worthwhile speed increase? :)Michalemichalski
FYI Zend Server includes Optimizer+ which is Zend's opcode optimizer and cache, equivalent of APC but according to some benchmarks (e.g. zimuel.it/blog/2010/06/benchmarking-zend-server-ce-with-joomla) is faster, at least in some cases, than APC. So while you can enable APC on it you don't really need to.Mashie
It wont help for little project (small cms) but if will help with many included files. require_once has to check the includes list every time before inclusion and lowers the performance of autoloading. With tweaked supersimple autoloader and optimised inlcude path it works much better :) Also depends on how saturated you IO operations are.Brecher
I'm at a fork on the road regarding a design decision at the moment Tomas, and I'm analysing on whether or not to use a base class with several convenience methods rather than an action helper (I'm talkin' an actual ActionHelper not the "Action" Viewhelper or "ActionStack" action helper. Just so it's clear, you probably aren't, but if you are, are you saying that one should stay away from Action Helpers? if so, "why?" - TIA.Dittmer
You should use them as it helps reuseablity. It depends on the situation. It's not very good idea to have 20 action helpers used in every controller. Place to use ActionHelper is where it saves resources when NOT used and it's not used everywhere. If there is something you use all the time than I think that it's better to fallback to abstract Controller class that is extended by controllers.Brecher
Obvious advantage of actionhelpers is that they can be used in other projects as well ;)Brecher
@TomášFejfar Could you please explain why in your last point you said disable viewRenderer and take care of view rendering yourself will improve the performance ?! How can I handle the rendering myself?Duwalt
ViewRenderer magically render appropriate view on afterDispatch. It does a lot of things - like transforming MyController::someAction to /my/some.phtml and some other stuff. It also creates the view object automagically. Disable HOWTO: zend-framework-community.634137.n4.nabble.com/…Brecher
@TomášFejfar Thanks for link, will definitely check it out and sorry for the late reply, but u didn't tag me in the comment :DDuwalt
I updated my answer with new options and also clarified the action helper stuff. Only problem with action helpers is that they are looked up based on path stack - so with every new path each default helper needs one more stat call. So with 3 paths (AppHelper, MyNamespaceHelper, ZendHelper) there are 3 stat calls to find the right one! Keep that in mind.Brecher
Keep in mind that actionstack may be "slower" than doing all the work in a single dispatch, however, using actionstack is much faster (for the end user) than a redirect to the next action w/ an additional HTTP request.Stinnett
Good point Mike, but I think that you mostly use redirect in post-redirect-get situation and it's a scenario where user expects slower response - and redirect has additional advantage in droping the POST => no message "resend form data".Brecher
To add more - most prominent use of actionstack I've seen, was to use it to render menu and footer for each page - each in it's own response segment. I also used this at first as it seemed like a valid option (so does action view helper). But the performance drop taught me well not to use it! :)Brecher
M
3

APC will help no matter what sort of stack you're running on. Any sort of OPcode caching will.

In terms of speeding up your application, the first step is to profile it. Use Xdebug to generate a cachegrind report and then use something like kcachegrind or webgrind to interpret it.

From working with Zend Framework, here are some pain points I typically find:

  • Config files are pretty intensive to compute. once you have the final config object, cache it!
  • File includes are really expensive, try and get them down to a minimum. If you're opening files a lot for reflection based stuff, cache the output there.
  • Database calls can be expensive, but are typically not the bears in the room unless they're central tasks.

Page level caching will help tremendously. Anywhere where you dont need fresh data, cache it.

Past that its less of a Zend Framework or a server issue and it starts being architectural in nature. Can you farm off intensive tasks asynchronously? Sometimes it's not worth optimising something, but it is worth changing user perception to feel faster.

Amusing thought, the other day i backspaced over $i++ to replace it with ++$i. It's technically faster, but I'm sure the time it took me to do that will never be regained in the programs lifetime. You have to draw the line somewhere :)

Michalemichalski answered 17/1, 2011 at 4:47 Comment(0)
N
1

Zend Server is a very generally speaking PHP compiler (the P from LAMP or WAMP stack), however much more advanced, give you nice GUI to set everything (instead editing php.ini), but what more imported:

  • APC
  • Cache (data i page level)
  • Job quering
  • Advanced monitoring with debugging

If you looking for APC only maybe other solutions (what I do not know yet) could be cheaper, but need for APC suggest that you would like caching and job quering... I love it.

Zend Framework is not needed to use it, but you can use any framework (or without framework) you want.

Nice thing that you can try ZS full featured it for free for 30 days (APC is not availble in CE ---->>>> wrong APC IS avaible in CE)

Nila answered 16/1, 2011 at 23:22 Comment(0)
J
1

Op-code caching is the one extension you always want to use when running PHP in production. Apc is an op-code caching and data caching extension but in Zend server the primary op-code caching is called "Optimizer plus" and I recommend comparing the performance between the 2 before deciding to use APC. There is also another extension in Zend server which does the data caching job. Many file includes (like in Zend framework) are no longer a problem with op-code caching since they are stored compiled in memory and does not take long any more to start using them.

Another major performance gain can be achieved with the full (paid) version of Zend server by using the PHP monitoring combined with code tracing which gives valuable information regarding problems and un-optimized code in your application. problems like long scripts and function execution, long DB queries, and more can be solved very fast with this combination.

Jamesjamesian answered 17/1, 2011 at 8:37 Comment(0)
C
0

The Source This tip is not new. It is taken directly from the Zend Framework Documentation at: Zend Framework Performance Guide and I used what was written with few things I’ve skip.

Use Zend_Loader and Remove All require_once

We can’t actually remove all require_once statements. We must have at least one require_once to load the Zend_Loader. First, activate Zend Loader.

require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

Next would be removing all require_once statements on all files inside the Zend directory. If you are using Eclipse PDT, you can use the find and replace function.

Cache Zend_Db_Table MetaData with Zend_Cache

When you are using Zend_Db_Table (I sometimes only used Zend_Db) you will notice that when you try to retrieve data from the database, the first query called is to DESCRIBE the table. Zend_Db_Table uses the information on DESCRIBE query to do its magic on SELECT.

As I have profiled my queries, I noticed that DESCRIBE query is the longest query (in most cases) which mean a big overhead over you retrieval operation. You have two options:

(A) Don’t use Zend_Db_Table (go for Zend_Db) (B) Cache the MetaData

On this post, I’ll use the caching of MetaData. On your bootstrap file, put this piece of code:

//Caching
$frontendOptions = array(
                    'lifetime'                  => 25200,
                    'automatic_serialization'   => true
                    );
$backendOptions  = array(
                     'cache_dir'                => APPLICATION_PATH . '/tmp'
                    );          
$cache = Zend_Cache::factory(
                    'Core',
                    'File',
                    $frontendOptions,
                    $backendOptions
                    );
//Cache table metadata
Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);

Cache Plugin Loader Class File

When using a plugin, Zend Framework includes several files depending on the plugin used and process several iterations to find the right plugin and include it. With code code below, it creates a list of include_once statements to include those plugin files. Just include this piece of code to your bootstrap.

//Plugin Loader caching
$classFileIncCache = APPLICATION_PATH .  '/data/pluginLoaderCache.php';
if (file_exists($classFileIncCache)) {
    include_once $classFileIncCache;
}
Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);

Caching Your Data

Caching your data will be the most important part of optimization which will save you a lot of database access when repeatedly accessed data already cache. It is important to set the cache expiration time and also clear the cache when data changes. A simple caching is shown below.

On your bootstrap:

//Caching
$frontendOptions = array(
                    'lifetime'                  => 25200,
                    'automatic_serialization'   => true
                    );
$backendOptions  = array(
                     'cache_dir'                => APPLICATION_PATH . '/tmp'
                    );          
$cache = Zend_Cache::factory(
                    'Core',
                    'File',
                    $frontendOptions,
                    $backendOptions
                    );

$registry->set('cache', $dbCache);

This are the basic settings which may helpful I think.

Cattle answered 5/4, 2019 at 9:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.