The definitive guide of Symfony 1.0

18.3. Tweaking the View

According to how you design and implement the view layer, you may notice small slowdowns or speedups. This section describes the alternatives and their tradeoffs.

18.3.1. Using the Fastest Code Fragment

If you don't use the caching system, you have to be aware that an include_component() is slightly slower than an include_partial(), which itself is slightly slower than a simple PHP include. This is because symfony instantiates a view to include a partial and an object of class sfComponent to include a component, which collectively add some minor overhead beyond what's required to include the file.

However, this overhead is insignificant, unless you include a lot of partials or components in a template. This may happen in lists or tables, and every time you call an include_partial() helper inside a foreach statement. When you notice that a large number of partial or component inclusions have a significant impact on your performance, you may consider caching (see Chapter 12), and if caching is not an option, then switch to simple include statements.

As for slots and component slots, the difference in performance is perceptible. The process time necessary to set and include a slot is negligible — it is equivalent to a variable instantiation. But component slots rely on a view configuration, and they require a few objects to be initiated to work. However, component slots can be cached independently from the calling templates, while slots are always cached within the template that includes them.

18.3.2. Speeding Up the Routing Process

As explained in Chapter 9, every call to a link helper in a template asks the routing system to process an internal URI into an external URL. This is done by finding a match between the URI and the patterns of the routing.yml file. Symfony does it quite simply: It tries to match the first rule with the given URI, and if it doesn't work, it tries with the following, and so on. As every test involves regular expressions, this is quite time consuming.

There is a simple workaround: Use the rule name instead of the module/action couple. This will tell symfony which rule to use, and the routing system won't lose time trying to match all previous rules.

In concrete terms, consider the following routing rule, defined in your routing.yml file:

article_by_id:
  url:          /article/:id
  param:        { module: article, action: read }

Then instead of outputting a hyperlink this way:

<?php echo link_to('my article', 'article/read?id='.$article->getId()) ?>

you should use the fastest version:

<?php echo link_to('my article', '@article_by_id?id='.$article->getId()) ?>

The difference starts being noticeable when a page includes a few dozen routed hyperlinks.

18.3.3. Skipping the Template

Usually, a response is composed of a set of headers and content. But some responses don't need content. For instance, some Ajax interactions need only a few pieces of data from the server in order to feed a JavaScript program that will update different parts of the page. For this kind of short response, a set of headers alone is faster to transmit. As discussed in Chapter 11, an action can return only a JSON header. Listing 18-12 reproduces an example from Chapter 11.

Listing 18-12 - Example Action Returning a JSON Header

public function executeRefresh()
{
  $output = '<"title", "My basic letter"], ["name", "Mr Brown">';
  $this->getResponse()->setHttpHeader("X-JSON", '('.$output.')');

  return sfView::HEADER_ONLY;
}

This skips the template and the layout, and the response can be sent at once. As it contains only headers, it is more lightweight and will take less time to transmit to the user.

Chapter 6 explained another way to skip the template by returning content text directly from the action. This breaks the MVC separation, but it can increase the responsiveness of an action greatly. Check Listing 18-13 for an example.

Listing 18-13 - Example Action Returning Content Text Directly

public function executeFastAction()
{
  return $this->renderText("<html><body>Hello, World!</body></html>");
}

18.3.4. Restricting the Default Helpers

The standard helper groups (Partial, Cache, and Form) are loaded for every request. If you are sure that you won't use some of them, removing a helper group from the list of standard ones will save you the parsing of the helper file. In particular, the Form helper group, although included by default, is quite heavy and slows down pages with no forms just because of its size. So it might be a good idea to edit the standard_helpers setting in the settings.yml file to remove it:

all:
  .settings:
    standard_helpers: [Partial, Cache]    # Form is removed

The tradeoff is that you must declare the Form helper group on each template using it with use_helper('Form').

18.3.5. Compressing the Response

Symfony compresses the response before sending it to the user. This feature is based on the PHP zlib module. You can save a little CPU time for each request by deactivating it in the settings.yml file:

all:
  .settings:
    compressed: off

Be aware that the CPU gain will be balanced by the bandwidth loss, so the performance won't increase in all configurations with this change.

Tip If you deactivate zip compression in PHP, you can enable it at the server level. Apache has a compression extension of its own.