Nicolas Grekas
Contributed by Nicolas Grekas in #36195 and #36209

PHP class preloading is one of the most important features added in PHP 7.4. On server startup - before any application code is run - PHP can load a certain set of PHP files into memory and make their contents permanently available to all subsequent requests.

During preloading, PHP also resolves class dependencies and links with parent, interfaces and traits. It also removes unnecessary includes and performs some other optimizations. The overall result is a very significant performance improvement in real applications.

Symfony is compatible with PHP preloading since 4.4 version. In Symfony 5.1 we've improved preloading to make it easier to configure thanks to two new dependency injection tags called container.preload and container.no_preload.

First, container.preload allows you to define which classes must be preloaded by PHP. Add one or more of these tags in your services to preload as many classes as you need. For example, in Symfony code we use this tag to preload some classes related to the twig service:

1
2
3
4
5
6
7
8
9
10
services:
    twig:
        class: Twig\Environment
        # ...
        tags:
            - { name: 'container.preload', class: 'Twig\Cache\FilesystemCache' }
            - { name: 'container.preload', class: 'Twig\Extension\CoreExtension' }
            - { name: 'container.preload', class: 'Twig\Extension\EscaperExtension' }
            - { name: 'container.preload', class: 'Twig\Extension\OptimizerExtension' }
            # ...

The container.no_preload tag is used to tell PHP that it must not preload a certain class. In this case, the tag doesn't define a class attribute. Instead, apply the tag to some service and the class related to that service won't be preloaded:

1
2
3
4
5
6
services:
    twig.template_cache_warmer:
        class: Symfony\Bundle\TwigBundle\CacheWarmer\TemplateCacheWarmer
        # ...
        tags:
            - { name: 'container.no_preload' }

Another change related to PHP preloading is that the warmUp() method of the Symfony cache warmers now must return an array with the FQCN (fully-qualified class names) of the classes to warm up. Not doing that is deprecated since Symfony 5.1.

We've already implemented all these features in Symfony code. The result is that in our synthetic benchmarks, a sample application went from 360 requests per second to 630 requests per second, a 75% performance improvement.

In your own applications, performance improvements will vary. To learn more about preloading in Symfony applications, sign up for the next SymfonyLive Online event which will take place on Friday, April 17.

Published in #Living on the edge