Skip to content

Commit 6cb4f6a

Browse files
bug #49679 [FrameworkBundle] enable metadata cache when annotation is disabled (bastnic)
This PR was merged into the 5.4 branch. Discussion ---------- [FrameworkBundle] enable metadata cache when annotation is disabled | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> When using Annotations, annotations are cached at `AnnotationLoader` level. Which is cleared when entities are changed. So the dev experience is optimal. ``` [ClassMetadataFactory.php](vendor/symfony/serializer/Mapping/Factory/ClassMetadataFactory.php") on line 51: [Symfony\Component\Serializer\Mapping\Loader\LoaderChain](vendor/symfony/serializer/Mapping/Loader/LoaderChain.php&line=28#line28) {#543 ▼ -loaders: array:1 [▼ 0 => [Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader](vendor/symfony/serializer/Mapping/Loader/AnnotationLoader.php&line=33#line33) {#544 ▼ -reader: [Doctrine\Common\Annotations\PsrCachedReader](vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php&line=22#line22) {#262 ▼ -delegate: [Doctrine\Common\Annotations\AnnotationReader](vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php&line=20#line20) {#263 ▶} -cache: [Symfony\Component\Cache\Adapter\PhpArrayAdapter](vendor/symfony/cache/Adapter/PhpArrayAdapter.php&line=32#line32) {#277 ▶} -debug: true -loadedAnnotations: array:14 [▶] -loadedFilemtimes: array:4 [▶] } } ] } ``` When using yaml files, there is no cache at the loader level so I added in the past the same cache as for the prod env, as the metadata are effectively cleared when using only yaml config files. symfony/symfony#35109 The regression introduced by my patch is for people that do not use mapping files but use annotations. symfony/symfony#41961 But now, we are in the opposite situation: no cache for people using mapping files but not annotations. On a current project it means loading 83 yaml files for each dev requests. It's not good at all. A simple local fix is to add that in a dev services files. ```yaml serializer.mapping.cache_class_metadata_factory: class: 'Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory' decorates: 'serializer.mapping.class_metadata_factory' arguments: ['`@serializer`.mapping.cache_class_metadata_factory.inner', '`@serializer`.mapping.cache.symfony'] ``` ![image](https://user-images.githubusercontent.com/84887/224833940-b8e7ad72-e7f6-44e7-a924-0b20f2f0cdae.png) A solution in Symfony could be: 1/ only yaml/xml mapping files (`enable_annotations: false`) : cache like prod => that what I did in this PR, as it fixes the current perf regressions on my different projects. There is no cache on yaml/xml file as soon as annotation is enabled (which is the default) 2/ add a cache at reader level for yaml/xml loader 3/ add a cache cleaner at metadata level when annotation are enabled Commits ------- 1773dff5ce [FrameworkBundle] enable metadata cache when annotation is disabled
2 parents 1294218 + bef7174 commit 6cb4f6a

File tree

5 files changed

+49
-5
lines changed

5 files changed

+49
-5
lines changed

DependencyInjection/FrameworkExtension.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,9 +1769,6 @@ private function registerSecurityCsrfConfiguration(array $config, ContainerBuild
17691769
private function registerSerializerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader)
17701770
{
17711771
$loader->load('serializer.php');
1772-
if ($container->getParameter('kernel.debug')) {
1773-
$container->removeDefinition('serializer.mapping.cache_class_metadata_factory');
1774-
}
17751772

17761773
$chainLoader = $container->getDefinition('serializer.mapping.chain_loader');
17771774

@@ -1797,6 +1794,9 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
17971794
if (\PHP_VERSION_ID < 80000 && !$this->annotationsConfigEnabled) {
17981795
throw new \LogicException('"enable_annotations" on the serializer cannot be set as the PHP version is lower than 8 and Annotations support is disabled. Consider upgrading PHP.');
17991796
}
1797+
if ($container->getParameter('kernel.debug')) {
1798+
$container->removeDefinition('serializer.mapping.cache_class_metadata_factory');
1799+
}
18001800

18011801
$annotationLoader = new Definition(
18021802
'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader',
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
$container->loadFromExtension('framework', [
4+
'serializer' => [
5+
'enable_annotations' => false,
6+
'mapping' => [
7+
'paths' => [
8+
'%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files',
9+
'%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml',
10+
'%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml',
11+
],
12+
],
13+
],
14+
]);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xmlns:framework="http://symfony.com/schema/dic/symfony">
6+
7+
<framework:config>
8+
<framework:serializer enable-annotations="false">
9+
<framework:mapping>
10+
<framework:path>%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files</framework:path>
11+
<framework:path>%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml</framework:path>
12+
<framework:path>%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml</framework:path>
13+
</framework:mapping>
14+
</framework:serializer>
15+
</framework:config>
16+
</container>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
framework:
2+
serializer:
3+
enable_annotations: false
4+
mapping:
5+
paths:
6+
- "%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files"
7+
- "%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml"
8+
- "%kernel.project_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml"

Tests/DependencyInjection/FrameworkExtensionTestCase.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,9 +1527,15 @@ public function testSerializerCacheActivated()
15271527
$this->assertEquals(new Reference('serializer.mapping.cache.symfony'), $cache);
15281528
}
15291529

1530-
public function testSerializerCacheNotActivatedDebug()
1530+
public function testSerializerCacheUsedWithoutAnnotationsAndMappingFiles()
15311531
{
1532-
$container = $this->createContainerFromFile('serializer_enabled', ['kernel.debug' => true, 'kernel.container_class' => __CLASS__]);
1532+
$container = $this->createContainerFromFile('serializer_mapping_without_annotations', ['kernel.debug' => true, 'kernel.container_class' => __CLASS__]);
1533+
$this->assertTrue($container->hasDefinition('serializer.mapping.cache_class_metadata_factory'));
1534+
}
1535+
1536+
public function testSerializerCacheNotActivatedWithAnnotations()
1537+
{
1538+
$container = $this->createContainerFromFile('serializer_mapping', ['kernel.debug' => true, 'kernel.container_class' => __CLASS__]);
15331539
$this->assertFalse($container->hasDefinition('serializer.mapping.cache_class_metadata_factory'));
15341540
}
15351541

0 commit comments

Comments
 (0)