Intro
First of all, I got my inspiration from this article, which was mentioned on A Week of Symfony #719. As Margaret mentions, Sylius would be a good use case to add these improvements to. So said and done.
Setup
- OS: Fedora 32
- RAM: 12 gig DDR3
- Database: MariaDB 10.4.11 - Docker Container
- PHP Server: Symfony CLI - PHP 7.4.11
- Default Sylius installation
- APP_ENV=prod, APP_DEBUG=0
The changes
For each bundle found in the src\Sylius\Bundle
, I searched for Twig extensions. Only extensions that had dependencies I ported to a Runtime Extension. I made all the changes in one commit, so I would be able to easily go back and forth between the original installation and the adjusted code.
So this
ProvinceNamingExtension.php
<?php
...
class ProvinceNamingExtension extends AbstractExtension
{
/** @var ProvinceNamingProviderInterface */
private $provinceNamingProvider;
public function __construct(ProvinceNamingProviderInterface $provinceNamingProvider)
{
$this->provinceNamingProvider = $provinceNamingProvider;
}
public function getFilters(): array
{
return [
new TwigFilter('sylius_province_name', [$this->provinceNamingProvider, 'getName']),
new TwigFilter('sylius_province_abbreviation', [$this->provinceNamingProvider, 'getAbbreviation']),
];
}
}
Became this:
ProvinceNamingExtension.php
<?php
...
class ProvinceNamingExtension extends AbstractExtension
{
public function getFilters(): array
{
return [
new TwigFilter('sylius_province_name', [ProvinceNamingRuntimeExtension::class, 'getName']),
new TwigFilter('sylius_province_abbreviation', [ProvinceNamingRuntimeExtension::class, 'getAbbreviation']),
];
}
}
ProvinceNamingRuntimeExtension.php
<?php
...
class ProvinceNamingRuntimeExtension implements RuntimeExtensionInterface
{
/** @var ProvinceNamingProviderInterface */
private $provinceNamingProvider;
public function __construct(ProvinceNamingProviderInterface $provinceNamingProvider)
{
$this->provinceNamingProvider = $provinceNamingProvider;
}
public function getName($address)
{
return $this->provinceNamingProvider->getName($address);
}
public function getAbbreviation($address)
{
return $this->provinceNamingProvider->getAbbreviation($address);
}
}
Profiling
I used Blackfire.io as a profiling tool. I ran the tests on /en_US/taxons/category/dresses
. Before each profile, I manually removed the var/cache
folder, ran php bin/console cache:clear
, and gave the page one refresh.
The default installation profile:
Some stats:
- Avg. Request time: 396 ms
- Avg. IO Wait: 8.44 ms
- Avg CPU Time: 361 ms
- Avg. Peak Memory: 48.8MB
Updated code profile:
Some stats:
- Avg. Request time: 362 ms
- Avg. IO Wait: 7.52 ms
- Avg CPU Time: 355 ms
- Avg. Peak Memory: 48.3MB
Comparison:
Luckily for me, Blackfire itself supports making comparisons between two profiles. These are the results:
- Diff. Request time: -7ms (1.9%)
- Diff. IO Wait: -922µs (11.%)
- Diff CPU Time: -6.08 ms (1.68%)
- Diff. Peak Memory: -84kb (0.174%)
Conclusion
While the tone in the inspiring article 'suggested' these changes would make a big difference, I find the difference quite small. But It also depends on how much extensions are loaded for that page. Anyhow, each positive change is a good change. So I'd suggest, if you create a Twig extension that has dependencies, just create them as runtime extensions.