7 Ways to speed up your Symfony Setup
September 28, 2019 in Tutorials
Speed in todays modern world is a critical thing, isn't it? Users jump aboard if your website or webapp isn't loading fast enough, Google punishes you with bad rankings, your revenue decreases, and you are falling behind your competitors, even though you might provide good value to your customers.
With the increased hunger for speed, tradeoffs are inevitable sometimes. So let's try to build a setup using Symfony framework that is as fast as possible, but still doesn't impose too many programming restrictions on ourselves.
Server / Docker Setup
Optimizing the server setup is the first ground to win for you, and it should be a pretty easy one too. Optimizing at this stage also imposes nearly none restrictions for developers, basically making this a one time investment with long term effects.
1. Using OPcache Byte Code Cache
The OPcache stores the compiled PHP files which avoids recompilation of those for each request.
Installing OPcache for Ubuntu 19.04
To install OPcache on Ubuntu 19.04, execute the following command:
sudo apt install php7.2-opcache
Installing OPcache for Docker php:7.x-apache
To install OPcache using the PHP Docker image, add the following line to your Dockerfile:
RUN docker-php-ext-install opcache
Enabling and configuring OPcache
Of course, only installing the extension won't magically turn it on, that's why you need to put the following configuration into your php.ini file.
; enables opcache opcache.enable=1 ; 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 for timestamps opcache.validate_timestamps=0
This will not only enable opcache for your PHP environment, it will also tweak the settings to get the best performance out of your opcache.
2. PHP Tweaks
Another thing you are able to do is to allow PHP to cache a lot more of those relative to absolute path mappings it has to do at runtime by setting the following configuration option in your php.ini file.
; maximum memory allocated to store the results realpath_cache_size=4096K ; save the results for 1 hour (3600 seconds) realpath_cache_ttl=3600
This reduces the amount of times PHP has to look up a mapping for a relative path to an absolute path dramatically, since nearly all of the mappings in a typical symfony application are now able to be cached, improving overall performance of your website.
3. Compressing your assets
Configuring your webserver to compress assets before delivering them to your end users also improves the performance of your website.
Of course, enabling compression of assets will also result in more work being done on the server before sending the files, but for nearly all use cases the compression performance of the server outperforms the connection with which your end users are receiving your content.
Add the following configuration to your vhost configuration in apache to enable compression for your website.
4. To .htaccess or not to .htaccess
Last but not least let's quickly talk about a .htaccess file. Having one is quite common for most projects out there running on apache. But if you have the luxury to, you should avoid using it.
Why should you avoid using it? Those .htaccess files are dynamically loaded, which made them quite popular in the first place, and because they are easy to use when you are tied to a webspace only solution.
But having those files loaded over and over again with every request is just adding overhead to every request. A better way to do this is to put whatever is in your .htaccess file, into the vhost server configuration itself. This way it's only going to be loaded once while the server boots up, and kept in memory for every request.
After you have configured your server for maximum performance, you should also consider optimizing your deployment procedure. 'Cause the server is only executing what you are handing over to it, so let's optimize a little of what we are handing over.
5. Environment aware build process
We are speaking about symfonys
APP_ENV variable here.
It is advisable to set this variable to prod before you are executing commands with
Why? At first,
APP_ENV=prod is the settings which tells symfony to skip loading up dependencies installed in your application which are only neccessary for development purposes. Since you are building your application for producation, settings this variable to prod seems to make sense.
Second, by default symfony registers hooks which are clearing the caches and installing the assets. These hooks are environment aware, so ensuring that these hooks are able to work their best is a must when striving for good web performance.
6. Composer Optimizations
Excluding development dependencies from runtime bootstrapping is good, but what is even better is not shipping them at all. It's adivsable to use the following command for installing your dependencies when building for production.
composer install --optimize-autoloader --no-dev --classmap-authoritative
So, what is this doing?
--optimize-autoloaderThis prevents PHP from having to do a lot of filesystem look ups for PSR-4/PSR-0 rules. These lookups are resolved beforehand and saved using relative paths.
--no-devAs the name implies, this prevents all the development dependencies from being installed, reducing vendor folder size and classmap file size.
--classmap-authoritativeThis basically prevents PHP from dynamically looking up classes that are not present in the classmap generated by composer.
The above steps all are one-time investments, which means you have to fiddle with those settings only once during the lifetime of your website.
If your website is not doing all too much heavy lifting, these optimizations should be sufficient to get you and your customers happy with the performance.
If you are still not happy, you can also change the way your application is loading itself up and how content is served to your end users.
7. Lazy services
Using lazy services allows you to inject services lazily into you services. Which means technically only a reference to a proxy is injected into your service, instead a reference to the already fully bootstrapped service.
In order to use lazy services, you'll need the package
composer install symfony/proxy-manager-bridge
This in turn allows you to write service definitions like the following in your services.yaml.
services: App\Twig\AppExtension: lazy: true
This will make the AppExtension service a lazy one, which means it will only be constructed if it is used activly by another service or controller in your application.
Having enabled some or all of the above steps should reduce the ramp up and delivery time of you symfony webapp or website a lot! There are of course always other and maybe also more advanced methods to further optimize your application, but in this post we were focusing only on the things you are able to do which are not or not heavily interfering with the way you are writing your code.