Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • SensioLabs Professional services to help you with Symfony
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by SensioLabs
  1. Home
  2. Documentation
  3. Performance
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud

Table of Contents

  • Performance Checklists
    • Install APCu Polyfill if your Server Uses APC
    • Dump the Service Container into a Single File
    • Use the OPcache Byte Code Cache
    • Use the OPcache class preloading
    • Configure OPcache for Maximum Performance
    • Don't Check PHP Files Timestamps
    • Configure the PHP realpath Cache
    • Optimize Composer Autoloader
  • Profiling Symfony Applications
    • Profiling with Blackfire
    • Profiling with Symfony Stopwatch
  • Learn more

Performance

Edit this page

Warning: You are browsing the documentation for Symfony 4.4, which is no longer maintained.

Read the updated version of this page for Symfony 6.2 (the current stable version).

Performance

Symfony is fast, right out of the box. However, you can make it faster if you optimize your servers and your applications as explained in the following performance checklists.

Performance Checklists

Use these checklists to verify that your application and server are configured for maximum performance:

  • Symfony Application Checklist:

    1. Install APCu Polyfill if your server uses APC
  • Production Server Checklist:

    1. Dump the service container into a single file
    2. Use the OPcache byte code cache
    3. Configure OPcache for maximum performance
    4. Don't check PHP files timestamps
    5. Configure the PHP realpath Cache
    6. Optimize Composer Autoloader

Install APCu Polyfill if your Server Uses APC

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.

Dump the Service Container into a Single File

4.4

The container.dumper.inline_factories parameter was introduced in Symfony 4.4.

Symfony compiles the service container into multiple small files by default. Set this parameter to true to compile the entire container into a single file, which could improve performance when using "class preloading" in PHP 7.4 or newer versions:

  • YAML
  • XML
  • PHP
1
2
3
4
# config/services.yaml
parameters:
    # ...
    container.dumper.inline_factories: true
1
2
3
4
5
6
7
8
9
10
11
<!-- config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">

    <parameters>
        <!-- ... -->
        <parameter key="container.dumper.inline_factories">true</parameter>
    </parameters>
</container>
1
2
3
4
// config/services.php

// ...
$container->parameters()->set('container.dumper.inline_factories', true);

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.

Use the OPcache class preloading

4.4

The feature that generates the preloading file was introduced in Symfony 4.4.

Starting from PHP 7.4, OPcache can compile and load classes at start-up and make them available to all requests until the server is restarted, improving performance significantly.

During container compilation (e.g. when running the cache:clear command), Symfony generates a file called preload.php in the config/ directory with the list of classes to preload.

You can configure PHP to use this preload file:

1
2
3
4
5
; php.ini
opcache.preload=/path/to/project/config/preload.php

; required for opcache.preload:
opcache.preload_user=www-data

If this file is missing, run this command to update the Symfony Flex recipe: composer recipes:update symfony/framework-bundle.

Configure OPcache for Maximum Performance

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

1
2
3
4
5
6
; php.ini
; maximum memory that OPcache can use to store compiled PHP files
opcache.memory_consumption=256

; maximum number of files that can be stored in the cache
opcache.max_accelerated_files=20000

Don't Check PHP Files Timestamps

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 they were cached. This check introduces some overhead that can be avoided as follows:

1
2
; php.ini
opcache.validate_timestamps=0

After each deployment, you must empty and regenerate the cache of OPcache. Otherwise you won't see the updates made in the application. Given that in PHP, the CLI and the web processes don't share the same OPcache, you cannot clear the web server OPcache by executing some command in your terminal. These are some of the possible solutions:

  1. Restart the web server;
  2. 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);
  3. Use the cachetool utility to control APC and OPcache from the CLI.

Configure the PHP realpath Cache

When a relative path is transformed into its real and absolute path, PHP caches the result to improve performance. Applications that open many PHP files, such as Symfony projects, should use at least these values:

1
2
3
4
5
6
; php.ini
; maximum memory allocated to store the results
realpath_cache_size=4096K

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

Note

PHP disables the realpath cache when the open_basedir config option is enabled.

Optimize Composer Autoloader

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 optimize Composer's autoloader to scan the entire application once and build an optimized "class map", which is a big array of the locations of all the classes and it's stored in vendor/composer/autoload_classmap.php.

Execute this command to generate the new class map (and make it part of your deployment process too):

1
$ composer dump-autoload --no-dev --classmap-authoritative
  • --no-dev excludes the classes that are only needed in the development environment (i.e. require-dev dependencies and autoload-dev rules);
  • --classmap-authoritative creates a class map for PSR-0 and PSR-4 compatible classes used in your application and prevents Composer from scanning the file system for classes that are not found in the class map. (see: Composer's autoloader optimization).

Profiling Symfony Applications

Profiling with Blackfire

Blackfire is the best tool to profile and optimize performance of Symfony applications during development, test and production. It's a commercial service, but provides free features that you can use to find bottlenecks in your projects.

Profiling with Symfony Stopwatch

Symfony provides a basic performance profiler in the development config environment. Click on the "time panel" of the web debug toolbar to see how much time Symfony spent on tasks such as making database queries and rendering templates.

You can measure the execution time and memory consumption of your own code and display the result in the Symfony profiler thanks to the Stopwatch component.

When using autowiring, type-hint any controller or service argument with the Stopwatch class and Symfony will inject the debug.stopwatch service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
use Symfony\Component\Stopwatch\Stopwatch;

class DataExporter
{
    private $stopwatch;

    public function __construct(Stopwatch $stopwatch)
    {
        $this->stopwatch = $stopwatch;
    }

    public function export()
    {
        // the argument is the name of the "profiling event"
        $this->stopwatch->start('export-data');

        // ...do things to export data...

        // reset the stopwatch to delete all the data measured so far
        // $this->stopwatch->reset();

        $this->stopwatch->stop('export-data');
    }
}

If the request calls this service during its execution, you'll see a new event called export-data in the Symfony profiler.

The start(), stop() and getEvent() methods return a StopwatchEvent object that provides information about the current event, even while it's still running. This object can be converted to a string for a quick summary:

1
2
// ...
dump((string) $this->stopwatch->getEvent()); // dumps e.g. '4.50 MiB - 26 ms'

You can also profile your template code with the stopwatch Twig tag:

1
2
3
4
5
{% stopwatch 'render-blog-posts' %}
    {% for post in blog_posts %}
        {# ... #}
    {% endfor %}
{% endstopwatch %}

Profiling Categories

Use the second optional argument of the start() method to define the category or tag of the event. This helps keep events organized by type:

1
$this->stopwatch->start('export-data', 'export');

Profiling Periods

A real-world stopwatch not only includes the start/stop button but also a "lap button" to measure each partial lap. This is exactly what the lap() method does, which stops an event and then restarts it immediately:

1
2
3
4
5
6
7
8
9
10
11
12
$this->stopwatch->start('process-data-records', 'export');

foreach ($records as $record) {
    // ... some code goes here
    $this->stopwatch->lap('process-data-records');
}

$event = $this->stopwatch->stop('process-data-records');
// $event->getDuration(), $event->getMemory(), etc.

// Lap information is stored as "periods" within the event:
// $event->getPeriods();

Profiling Sections

Sections are a way to split the profile timeline into groups. Example:

1
2
3
4
5
6
7
8
9
10
$this->stopwatch->openSection();
$this->stopwatch->start('validating-file', 'validation');
$this->stopwatch->stopSection('parsing');

$events = $this->stopwatch->getSectionEvents('parsing');

// later you can reopen a section passing its name to the openSection() method
$this->stopwatch->openSection('parsing');
$this->stopwatch->start('processing-file');
$this->stopwatch->stopSection('parsing');

All events that don't belong to any named section are added to the special section called __root__. This way you can get all stopwatch events, even if you don't know their names, as follows:

1
2
3
foreach($this->stopwatch->getSectionEvents('__root__') as $event) {
    echo (string) $event;
}

Learn more

  • How to Use Varnish to Speed up my Website
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version
    We stand with Ukraine.
    Version:
    Symfony Code Performance Profiling

    Symfony Code Performance Profiling

    Peruse our complete Symfony & PHP solutions catalog for your web development needs.

    Peruse our complete Symfony & PHP solutions catalog for your web development needs.

    Symfony footer

    ↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

    Avatar of Julien Sanchez, a Symfony contributor

    Thanks Julien Sanchez (@sumbobyboys) for being a Symfony contributor

    1 commit • 2 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • Symfony at a Glance
      • Symfony Components
      • Case Studies
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • SymfonyConnect
      • Support
      • How to be Involved
      • Code of Conduct
      • Events & Meetups
      • Projects using Symfony
      • Downloads Stats
      • Contributors
      • Backers
    • Blog

      • Events & Meetups
      • A week of symfony
      • Case studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Documentation
      • Living on the edge
      • Releases
      • Security Advisories
      • SymfonyInsight
      • Twig
      • SensioLabs
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Deployed on

    Follow Symfony

    Search by Algolia