From 06f945f27840b53e57795dadbc38e76f7e11ab1c Mon Sep 17 00:00:00 2001 From: Horus3 Date: Mon, 24 Feb 2014 16:42:14 +0100 Subject: init --- .../manual/core/en/performance.view.html | 454 +++++++++++++++++++++ 1 file changed, 454 insertions(+) create mode 100644 zend/documentation/manual/core/en/performance.view.html (limited to 'zend/documentation/manual/core/en/performance.view.html') diff --git a/zend/documentation/manual/core/en/performance.view.html b/zend/documentation/manual/core/en/performance.view.html new file mode 100644 index 0000000..8d6cb11 --- /dev/null +++ b/zend/documentation/manual/core/en/performance.view.html @@ -0,0 +1,454 @@ + + + + + View Rendering - Zend Framework Manual + + + + + + + + +
+ + + + + + + + +
+ Internationalization (i18n) and Localization (l10n) + + + + +
+
+

View Rendering

+ + +

+ When using Zend Framework's MVC layer, chances are you will be using + Zend_View. Zend_View is performs well + compared to other view or templating engines; since view scripts + are written in PHP, you do not incur the overhead of compiling custom + markup to PHP, nor do you need to worry that the compiled + PHP is not optimized. However, Zend_View presents + its own issues: extension is done via overloading (view helpers), and a number of view + helpers, while carrying out key functionality do so with a performance + cost. +

+ +

How can I speed up resolution of view helpers?

+ + +

+ Most Zend_View "methods" are actually provided via + overloading to the helper system. This provides important flexibility to + Zend_View; instead of needing to extend + Zend_View and provide all the helper methods you may + utilize in your application, you can define your helper methods in separate + classes and consume them at will as if they were direct methods of + Zend_View. This keeps the view object itself relatively + thin, and ensures that objects are created only when needed. +

+ +

+ Internally, Zend_View uses the PluginLoader to look + up helper classes. This means that for each helper you call, + Zend_View needs to pass the helper name to the + PluginLoader, which then needs to determine the class name, load the + class file if necessary, and then return the class name so it may be + instantiated. Subsequent uses of the helper are much faster, as + Zend_View keeps an internal registry of loaded helpers, + but if you use many helpers, the calls add up. +

+ +

+ The question, then, is: how can you speed up helper resolution? +

+ +

Use the PluginLoader include file cache

+ + +

+ The simplest, cheapest solution is the same as for general + PluginLoader performance: use + the PluginLoader include file cache. Anecdotal + evidence has shown this technique to provide a 25-30% + performance gain on systems without an opcode cache, and a + 40-65% gain on systems with an opcode cache. +

+
+ +

Extend Zend_View to provide often used helper methods

+ + +

+ Another solution for those seeking to tune performance even + further is to extend Zend_View to manually add the + helper methods they most use in their application. Such helper + methods may simply manually instantiate the appropriate helper + class and proxy to it, or stuff the full helper implementation + into the method. +

+ +
  1. class My_View extends Zend_View
  2. +
  3. {
  4. +
  5.     /**
  6. +
  7.      * @var array Registry of helper classes used
  8. +
  9.      */
  10. +
  11.     protected $_localHelperObjects = array();
  12. +
  13.  
  14. +
  15.     /**
  16. +
  17.      * Proxy to url view helper
  18. +
  19.      *
  20. +
  21.      * @param  array $urlOptions Options passed to the assemble method
  22. +
  23.      *                           of the Route object.
  24. +
  25.      * @param  mixed $name The name of a Route to use. If null it will
  26. +
  27.      *                     use the current Route
  28. +
  29.      * @param  bool $reset Whether or not to reset the route defaults
  30. +
  31.      *                     with those provided
  32. +
  33.      * @return string Url for the link href attribute.
  34. +
  35.      */
  36. +
  37.     public function url(array $urlOptions = array(), $name = null,
  38. +
  39.         $reset = false, $encode = true
  40. +
  41.     ) {
  42. +
  43.         if (!array_key_exists('url', $this->_localHelperObjects)) {
  44. +
  45.             $this->_localHelperObjects['url'] = new Zend_View_Helper_Url();
  46. +
  47.             $this->_localHelperObjects['url']->setView($this);
  48. +
  49.         }
  50. +
  51.         $helper = $this->_localHelperObjects['url'];
  52. +
  53.         return $helper->url($urlOptions, $name, $reset, $encode);
  54. +
  55.     }
  56. +
  57.  
  58. +
  59.     /**
  60. +
  61.      * Echo a message
  62. +
  63.      *
  64. +
  65.      * Direct implementation.
  66. +
  67.      *
  68. +
  69.      * @param  string $string
  70. +
  71.      * @return string
  72. +
  73.      */
  74. +
  75.     public function message($string)
  76. +
  77.     {
  78. +
  79.         return "<h1>" . $this->escape($message) . "</h1>\n";
  80. +
  81.     }
  82. +
  83. }
+ + +

+ Either way, this technique will substantially reduce the + overhead of the helper system by avoiding calls to the + PluginLoader entirely, and either benefiting from autoloading or + bypassing it altogether. +

+
+
+ +

How can I speed up view partials?

+ + +

+ Those who use partials heavily and who profile their applications + will often immediately notice that the partial() view + helper incurs a lot of overhead, due to the need to clone the view + object. Is it possible to speed this up? +

+ +

Use partial() only when really necessary

+ + +

+ The partial() view helper accepts three arguments: +

+ +
    +
  • +

    + $name: the name of the view script to render +

    +
  • + +
  • +

    + $module: the name of the module in which the + view script resides; or, if no third argument is provided + and this is an array or object, it will be the + $model argument. +

    +
  • + +
  • +

    + $model: an array or object to pass to the + partial representing the clean data to assign to the view. +

    +
  • +
+ +

+ The power and use of partial() come from the second + and third arguments. The $module argument allows + partial() to temporarily add a script path for the + given module so that the partial view script will resolve to + that module; the $model argument allows you to + explicitly pass variables for use with the partial view. + If you're not passing either argument, use + render() instead! +

+ +

+ Basically, unless you are actually passing variables to the + partial and need the clean variable scope, or rendering a view + script from another MVC module, there is no reason to incur the + overhead of partial(); instead, use + Zend_View's built-in render() + method to render the view script. +

+
+
+ +

How can I speed up calls to the action() view helper?

+ + +

+ Version 1.5.0 introduced the action() view helper, + which allows you to dispatch an MVC action and capture its rendered + content. This provides an important step towards the DRY principle, + and promotes code reuse. However, as those who profile their + applications will quickly realize, it, too, is an expensive + operation. Internally, the action() view helper needs + to clone new request and response objects, invoke the dispatcher, + invoke the requested controller and action, etc. +

+ +

+ How can you speed it up? +

+ +

Use the ActionStack when possible

+ + +

+ Introduced at the same time as the action() view + helper, the ActionStack + consists of an action helper and a front controller plugin. + Together, they allow you to push additional actions to invoke + during the dispatch cycle onto a stack. If you are calling + action() from your layout view scripts, you may + want to instead use the ActionStack, and render your views to + discrete response segments. As an example, you could write a + dispatchLoopStartup() plugin like the following to + add a login form box to each page: +

+ +
  1. class LoginPlugin extends Zend_Controller_Plugin_Abstract
  2. +
  3. {
  4. +
  5.     protected $_stack;
  6. +
  7.  
  8. +
  9.     public function dispatchLoopStartup(
  10. +
  11.         Zend_Controller_Request_Abstract $request
  12. +
  13.     ) {
  14. +
  15.         $stack = $this->getStack();
  16. +
  17.         $loginRequest = new Zend_Controller_Request_Simple();
  18. +
  19.         $loginRequest->setControllerName('user')
  20. +
  21.                      ->setActionName('index')
  22. +
  23.                      ->setParam('responseSegment', 'login');
  24. +
  25.         $stack->pushStack($loginRequest);
  26. +
  27.     }
  28. +
  29.  
  30. +
  31.     public function getStack()
  32. +
  33.     {
  34. +
  35.         if (null === $this->_stack) {
  36. +
  37.             $front = Zend_Controller_Front::getInstance();
  38. +
  39.             if (!$front->hasPlugin('Zend_Controller_Plugin_ActionStack')) {
  40. +
  41.                 $stack = new Zend_Controller_Plugin_ActionStack();
  42. +
  43.                 $front->registerPlugin($stack);
  44. +
  45.             } else {
  46. +
  47.                 $stack = $front->getPlugin('ActionStack')
  48. +
  49.             }
  50. +
  51.             $this->_stack = $stack;
  52. +
  53.         }
  54. +
  55.         return $this->_stack;
  56. +
  57.     }
  58. +
  59. }
+ + +

+ The UserController::indexAction() method might then + use the $responseSegment parameter to indicate which + response segment to render to. In the layout script, you would + then simply render that response segment: +

+ +
  1. <?php $this->layout()->login ?>
+ + +

+ While the ActionStack still requires a dispatch cycle, this is + still cheaper than the action() view helper as it + does not need to clone objects and reset internal state. + Additionally, it ensures that all pre and post dispatch plugins are + invoked, which may be of particular concern if you are using + front controller plugins for handling ACL's to particular + actions. +

+
+ +

Favor helpers that query the model over action()

+ + +

+ In most cases, using action() is simply overkill. + If you have most business logic nested in your models and are + simply querying the model and passing the results to a view + script, it will typically be faster and cleaner to simply write + a view helper that pulls the model, queries it, and does + something with that information. +

+ +

+ As an example, consider the following controller action and view + script: +

+ +
  1. class BugController extends Zend_Controller_Action
  2. +
  3. {
  4. +
  5.     public function listAction()
  6. +
  7.     {
  8. +
  9.         $model = new Bug();
  10. +
  11.         $this->view->bugs = $model->fetchActive();
  12. +
  13.     }
  14. +
  15. }
  16. +
  17.  
  18. +
  19. // bug/list.phtml:
  20. +
  21. echo "<ul>\n";
  22. +
  23. foreach ($this->bugs as $bug) {
  24. +
  25.     printf("<li><b>%s</b>: %s</li>\n",
  26. +
  27.         $this->escape($bug->id),
  28. +
  29.         $this->escape($bug->summary)
  30. +
  31.     );
  32. +
  33. }
  34. +
  35. echo "</ul>\n";
+ + +

+ Using action(), you would then invoke it with the + following: +

+ +
  1. <?php $this->action('list', 'bug') ?>
+ + +

+ This could be refactored to a view helper that looks like the + following: +

+ +
  1. class My_View_Helper_BugList extends Zend_View_Helper_Abstract
  2. +
  3. {
  4. +
  5.     public function bugList()
  6. +
  7.     {
  8. +
  9.         $model = new Bug();
  10. +
  11.         $html  = "<ul>\n";
  12. +
  13.         foreach ($model->fetchActive() as $bug) {
  14. +
  15.             $html .= sprintf(
  16. +
  17.                 "<li><b>%s</b>: %s</li>\n",
  18. +
  19.                 $this->view->escape($bug->id),
  20. +
  21.                 $this->view->escape($bug->summary)
  22. +
  23.             );
  24. +
  25.         }
  26. +
  27.         $html .= "</ul>\n";
  28. +
  29.         return $html;
  30. +
  31.     }
  32. +
  33. }
+ + +

+ You would then invoke the helper as follows: +

+ +
  1. <?php $this->bugList() ?>
+ + +

+ This has two benefits: it no longer incurs the overhead of the + action() view helper, and also presents a more + semantically understandable API. +

+
+
+
+
+ + + + + + + + + +
+ Internationalization (i18n) and Localization (l10n) + + + + +
+
+ +
+ + \ No newline at end of file -- cgit v1.2.3