Skip to content

Updates in performance.rst #8410

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
219 changes: 91 additions & 128 deletions performance.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,97 @@
Performance
===========

Symfony is fast, right out of the box. Of course, if you really need speed,
there are many ways that you can make Symfony even faster. In this article,
you'll explore some of the ways to make your Symfony application even faster.
Symfony is fast, right out of the box. Of course, if you really need speed, the
following performance checklists show how to make your application even faster.

.. index::
single: Performance; Byte code cache

Use a Byte Code Cache (e.g. OPcache)
------------------------------------
Production Server Checklist
---------------------------

The first thing that you should do to improve your performance is to use a
"byte code cache". These caches store the compiled PHP files to avoid having
to recompile them for every request.
#. :ref:`Use the OPcache byte code cache <performance-use-opcache>`
#. :ref:`Configure OPcache for maximum performance <performance-configure-opcache>`
#. :ref:`Don't check PHP timestamps <performance-dont-check-timestamps>`
#. :ref:`Configure the PHP realpath Cache <performance-configure-realpath-cache>`
#. :ref:`Optimize Composer Autoloader <performance-optimize-composer-autoloader>`

There are a number of `byte code caches`_ available, some of which are open
source. As of PHP 5.5, PHP comes with `OPcache`_ built-in. For older versions,
the most widely used byte code cache is `APC`_.

.. tip::
.. _performance-use-opcache:

Use the OPcache byte code cache
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

OPcache stores the compiled PHP files to avoid having to recompile them for
every request. There are some `byte code caches`_ available, but as of PHP
5.5, PHP comes with `OPcache`_ built-in. For older versions, the most widely
used byte code cache is `APC`_.

.. _performance-configure-opcache:

Configure OPcache for maximum performance
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The default OPcache configuration is not suited for Symfony application, so
it's recommended to change these settings as follows:

.. code-block:: ini

; php.ini
; maximum memory that OPcache can use to store compiled PHP files
opcache.memory_consumption=256M

If your server still uses the legacy APC PHP extension, install the
`APCu Polyfill component`_ in your application to enable compatibility with
`APCu PHP functions`_ and unlock support for advanced Symfony features, such
as the APCu Cache adapter.
; maximum number of files that can be stored in the cache
opcache.max_accelerated_files=20000

Using a byte code cache really has no downside, and Symfony has been designed
to perform really well in this type of environment.
.. _performance-dont-check-timestamps:

Monitoring Source File Changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Don't check PHP timestamps
~~~~~~~~~~~~~~~~~~~~~~~~~~

Most byte code caches monitor the source files for changes. This ensures that if
the source of a file changes, the byte code is recompiled automatically.
This is really convenient, but it adds overhead.
In production servers, PHP files should never change, unless a new application
version is deployed. However, by default OPcache checks if cached files have
changed their contents since caching them. This check introduces some overhead
that can be avoided as follows:

For this reason, some byte code caches offer an option to disable these checks.
For example, to disable these checks in APC, simply add ``apc.stat=0`` to your
``php.ini`` configuration.
.. code-block:: ini

When disabling these checks, it will be up to the server administrators to
ensure that the cache is cleared whenever any source files change. Otherwise,
the updates you've made in the application won't be seen.
; php.ini

For the same reasons, the byte code cache must also be cleared when deploying
the application (for example by calling ``apc_clear_cache()`` PHP function when
using APC and ``opcache_reset()`` when using OPcache).
; after each deploy, call `opcache_reset()` or restart the web server
; to empty the cache and regenerate the cached files. Otherwise you won't
; see the updates made in the application
opcache.validate_timestamps=0

.. note::

In PHP, the CLI and the web processes don't share the same OPcache. This
means that you cannot clear the web server OPcache by executing some command
The OPcache is different for the web server and the command console.
You cannot clear the web server OPcache by executing some command
in your terminal. You either need to restart the web server or call the
``apc_clear_cache()`` or ``opcache_reset()`` functions via the web server
(i.e. by having these in a script that you execute over the web).
``opcache_reset()`` function via the web server (i.e. by having this in
a script that you execute over the web).

Optimizing all the Files Used by Symfony
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _performance-configure-realpath-cache:

By default, PHP's OPcache saves up to 2,000 files in the byte code cache. This
number is too low for the typical Symfony application, so you should set a
higher limit with the `opcache.max_accelerated_files`_ configuration option:
Configure the PHP realpath Cache
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When a relative path is transformed into its real and absolute path, PHP
caches the result to improve performance. The default config of this cache
is not suited for applications that open many PHP files, such as Symfony.
It's recommended to change these settings as follows:

.. code-block:: ini

; php.ini
opcache.max_accelerated_files = 20000
; maximum memory allocated to store the results
realpath_cache_size=4096K

; save the results for 10 minutes (600 seconds)
realpath_cache_ttl=600


.. _performance-optimize-composer-autoloader:

Configure the PHP realpath Cache
--------------------------------
Expand All @@ -93,114 +118,54 @@ value too using the ``realpath_cache_ttl`` option:
.. index::
single: Performance; Autoloader

Use Composer's Class Map Functionality
--------------------------------------

By default, the Symfony Standard Edition uses Composer's autoloader
in the `autoload.php`_ file. This autoloader is easy to use, as it will
automatically find any new classes that you've placed in the registered
directories.
Optimize Composer Autoloader
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Unfortunately, this comes at a cost, as the loader iterates over all configured
namespaces to find a particular file, making ``file_exists()`` calls until it
finally finds the file it's looking for.

The simplest solution is to tell Composer to build an optimized "class map",
The class loader used while developing the application is optimized to find
new and changed classes. In production servers, PHP files should never change,
unless a new application version is deployed.
That's why you can use `Composer's autoloader optimization`
to scan the entire application once and build a "class map",
which is a big array of the locations of all the classes and it's stored
in ``vendor/composer/autoload_classmap.php``.

The class map can be generated from the command line, and might become part of
your deploy process:
Execute this command to generate the class map at install time (and thus make it part of your
deployment process too):

.. code-block:: bash

$ composer dump-autoload --optimize --no-dev --classmap-authoritative
$ composer install --no-dev --optimize-autoloader --classmap-authoritative --apcu-autoloader

``--optimize``
Dumps every PSR-0 and PSR-4 compatible class used in your application.
``--no-dev``
Excludes the classes that are only needed in the development environment
(e.g. tests).
``--optimize-autoloader``
Dumps every PSR-0 and PSR-4 compatible class used in your application.
``--classmap-authoritative``
Prevents Composer from scanning the file system for classes that are not
found in the class map.
``--apcu-autoloader``
You need to install APCu PHP extension to use this option.
It will cache the classmap in APCu. It won't generate the classmap though,
so you need to always use it with ``--optimize-autoloader``

Caching the Autoloader with APC
-------------------------------

Another solution is to cache the location of each class after it's located
the first time. Symfony comes with a class - :class:`Symfony\\Component\\ClassLoader\\ApcClassLoader` -
that does exactly this. To use it, just adapt your front controller file.
If you're using the Standard Distribution, make the following changes::

// app.php
// ...

use Symfony\Component\ClassLoader\ApcClassLoader;

// do not use $loader as a variable name here as it would
// be overwritten when loading the bootstrap.php.cache file
$classLoader = require __DIR__.'/../app/autoload.php';
include_once __DIR__.'/../app/bootstrap.php.cache';

// Use APC for autoloading to improve performance
// Change 'sf2' by the prefix you want in order
// to prevent key conflict with another application
$loader = new ApcClassLoader('sf2', $classLoader);
$loader->register(true);

// ...
.. tip::

For more details, see :doc:`/components/class_loader/cache_class_loader`.
If your production server still uses the legacy APC PHP extension instead of
OPcache, install the `APCu Polyfill component`_ in your application to enable
compatibility with `APCu PHP functions`_ and unlock support for advanced Symfony
features, such as the APCu Cache adapter.

.. note::

When using the APC autoloader, if you add new classes, they will be found
When using the APCu autoloader, if you add new classes, they will be found
automatically and everything will work the same as before (i.e. no
reason to "clear" the cache). However, if you change the location of a
particular namespace or prefix, you'll need to flush your APC cache. Otherwise,
particular namespace or prefix, you'll need to flush your APCu cache. Otherwise,
the autoloader will still be looking at the old location for all classes
inside that namespace.

.. index::
single: Performance; Bootstrap files

Use Bootstrap Files
-------------------

To ensure optimal flexibility and code reuse, Symfony applications leverage
a variety of classes and 3rd party components. But loading all of these classes
from separate files on each request can result in some overhead. To reduce
this overhead, the Symfony Standard Edition provides a script to generate
a so-called `bootstrap file`_, consisting of multiple classes definitions
in a single file. By including this file (which contains a copy of many of
the core classes), Symfony no longer needs to include any of the source files
containing those classes. This will reduce disc IO quite a bit.

If you're using the Symfony Standard Edition, then you're probably already
using the bootstrap file. To be sure, open your front controller (usually
``app.php``) and check to make sure that the following line exists::

include_once __DIR__.'/../var/bootstrap.php.cache';

Note that there are two disadvantages when using a bootstrap file:

* the file needs to be regenerated whenever any of the original sources change
(i.e. when you update the Symfony source or vendor libraries);

* when debugging, one will need to place break points inside the bootstrap file.

If you're using the Symfony Standard Edition, the bootstrap file is automatically
rebuilt after updating the vendor libraries via the ``composer install`` command.

Bootstrap Files and Byte Code Caches
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Even when using a byte code cache, performance will improve when using a bootstrap
file since there will be fewer files to monitor for changes. Of course, if this
feature is disabled in the byte code cache (e.g. ``apc.stat=0`` in APC), there
is no longer a reason to use a bootstrap file.

Learn more
----------

Expand All @@ -209,9 +174,7 @@ Learn more

.. _`byte code caches`: https://en.wikipedia.org/wiki/List_of_PHP_accelerators
.. _`OPcache`: http://php.net/manual/en/book.opcache.php
.. _`opcache.max_accelerated_files`: http://php.net/manual/en/opcache.configuration.php#ini.opcache.max-accelerated-files
.. _`Composer's autoloader optimization`: https://getcomposer.org/doc/articles/autoloader-optimization.md
.. _`APC`: http://php.net/manual/en/book.apc.php
.. _`APCu Polyfill component`: https://github.com/symfony/polyfill-apcu
.. _`APCu PHP functions`: http://php.net/manual/en/ref.apcu.php
.. _`autoload.php`: https://github.com/symfony/symfony-standard/blob/master/app/autoload.php
.. _`bootstrap file`: https://github.com/sensiolabs/SensioDistributionBundle/blob/master/Composer/ScriptHandler.php