Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PhpArrayAdapter to cache metadata #1196

Merged
merged 2 commits into from Nov 7, 2020

Conversation

ossinkine
Copy link
Contributor

Closes #1186

cc @ostrolucky @dmaicher @nicolas-grekas

I see two weak places in this implementation:

  1. DoctrineMetadataCacheWarmer extends AbstractPhpFileCacheWarmer which also extended by ValidatorCacheWarmer, SerializerCacheWarmer and AnnotationsCacheWarmer (everywhere PhpArrayAdapter used) but it's marked as internal, so BC breaks possible here. I can avoid extending this class but a lot of code will be copy-pasted.
  2. Since PhpArrayAdapter requires Symfony cache I wrap Doctrine cache with DoctrineAdapter. If Doctrine cache is DoctrineProvider which wrap a Symfony cache we get a redudant chain of adapters. For example the chain PhpArrayAdapter -> DoctrineAdapter -> DoctrineProvider -> RedisAdapter can be simplified by removing DoctrineAdapter and DoctrineProvider: PhpArrayAdapter -> RedisAdapter. I've tried to create a compiler pass which remove this redundancy but get list of entity managers in compiler pass a little bit difficult. And maybe we can implement this simplification in Symfony framework bundle globally for all such cache chains.

What is your opinion about this?

@nicolas-grekas
Copy link
Member

AbstractPhpFileCacheWarmer is internal

That can be changed, PR welcome on symfony/symfony to discuss it there.

DoctrineAdapter -> DoctrineProvider

This would be better implemented on the bundle imho, as that would allow releasing the logic in sync with the feature provided here.

fabpot added a commit to symfony/symfony that referenced this pull request Aug 26, 2020
…ic (ossinkine)

This PR was submitted for the 3.4 branch but it was merged into the 5.2-dev branch instead.

Discussion
----------

[FrameworkBundle] Make AbstractPhpFileCacheWarmer public

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| License       | MIT

Introducing the PhpArrayAdapter was a great feature. It has proven itself well in the production.
Actually, using the adapter is closely related to warming up the cache for it. FrameworkBundle has an AbstractPhpFileCacheWarmer for conveniently creating a custom warmer.
But using it outside of the FrameworkBundle becomes more complicated because it is marked as internal.
I propose making it public and allow it to be used outside of the FrameworkBundle.

For example, I've proposed to cache Doctrine metadata using PhpArrayAdapter and the implementation uses AbstractPhpFileCacheWarmer doctrine/DoctrineBundle#1196

Commits
-------

a0fb442 Make AbstractPhpFileCacheWarmer public
$cacheWarmerDefinition->addTag('kernel.cache_warmer');
}

private function registerMetadataPhpArrayCache(string $entityManagerName, ContainerBuilder $container): void
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would personally prefer to not unnecessarily register new service if its only purpose is to inject it to warmer. Service should be instead just inlined, IMHO. Otherwise we are unnecessarily increasing public API surface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doctrine.orm.default_metadata_cache is the alias which refers to the cache service. How can I create inline service and refer the alias to it?

/**
* Removes redundant decorators such DoctrineAdapter -> DoctrineProvider -> AdapterInterface.
*/
class PhpArrayCachePass implements CompilerPassInterface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would prefer not having to maintain this in bundle forever. Can you please contribute this to Symfony core too? That way you will also get better feedback, as I'm not exactly confident about these internals.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand @nicolas-grekas has another opinion. Since this is just optimization we can merge without it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicolas didn't mean it doesn't make sense to contribute to Symfony, he said it needs to be merged to doctrine bundle anyways, as otherwise this feature would be available in next minor Symfony version only. But yeah I am also ok with just removing it for now, would make it easier to merge

Copy link
Member

@ostrolucky ostrolucky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests are DI only, very simplistic. Can we have test which asserts that cache is hit when loading metadata and not generated again? Also, can you provide some numbers so everyone can see what's the expected improvement?

Also, we probably need to mark a test as legacy so CI passes.
And of course, needs to be rebased as it has conflicts.

@ossinkine
Copy link
Contributor Author

Tests don't passed because AbstractPhpFileCacheWarmer marked as internal, @group legacy does not hide the errors

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Aug 31, 2020

Hmm, I didn't consider this aspect.
I'd be fine removing the annotation on branch 3.4 (4.4?) on Symfony.

fabpot added a commit to symfony/symfony that referenced this pull request Sep 2, 2020
… (ossinkine)

This PR was merged into the 3.4 branch.

Discussion
----------

[FrameworkBundle] Make AbstractPhpFileCacheWarmer public

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| License       | MIT

The same as #37951 but with 3.4 as base branch, see doctrine/DoctrineBundle#1196 (comment)

cc @nicolas-grekas

Commits
-------

b82d9a2 Make AbstractPhpFileCacheWarmer public
@ostrolucky ostrolucky linked an issue Oct 26, 2020 that may be closed by this pull request
@ostrolucky
Copy link
Member

Any chance for finishing this @ossinkine?

@ossinkine
Copy link
Contributor Author

@ostrolucky I can remove PhpArrayCachePass which optimizes cache adapter chaining right now and later publish PR to Symfony but I don't what tests you requested and I don't how much time it will take

@ostrolucky
Copy link
Member

Sounds good enough to me!

@ossinkine ossinkine force-pushed the issue-1186 branch 3 times, most recently from 092c8dc to 7d2d76d Compare October 27, 2020 15:15
@ossinkine
Copy link
Contributor Author

@ostrolucky I've removed the commit with optimizations, rebased the branch from the master and fixed code style issue except the one, I think proposed fix is a bad idea

@ostrolucky
Copy link
Member

How about this. Does that work for you @ossinkine?

@ostrolucky ostrolucky added this to the 2.2.0 milestone Oct 31, 2020
@stof
Copy link
Member

stof commented Oct 31, 2020

get list of entity managers in compiler pass a little bit difficult.

this could actually be simple. We can add a tag on the services and use that tag in the compiler pass

@@ -688,6 +688,13 @@ private function getOrmCacheDriverNode(string $name): ArrayNodeDefinition
->scalarNode('pool')->end()
->end();

if ($name === 'metadata_cache_driver') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this means we also need to create a new recipe for 2.2?

See https://github.com/symfony/recipes/blob/master/doctrine/doctrine-bundle/1.12/config/packages/prod/doctrine.yaml#L4 (it's used for 2.x currently as well via symlink)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should yes

@ossinkine
Copy link
Contributor Author

@ostrolucky since PHP Array Cache adapter is a decorator for another adapter I'm not sure metadata_cache_driver should be depreacated. Or you suppose there can't be cache misses?

@ostrolucky
Copy link
Member

ostrolucky commented Nov 1, 2020

If PHP Array Cache adapter is a decorator for another adapter, what happens right now when metadata_cache_driver is not set? I think ArrayAdapter is used then, so we should probably make sure same continues happening in 3.0.

Copy link
Member

@greg0ire greg0ire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please state the obvious. It would be great not to have to read several issues and PRs on different repositories to understand this.

DependencyInjection/Configuration.php Show resolved Hide resolved
DependencyInjection/DoctrineExtension.php Show resolved Hide resolved
ossinkine and others added 2 commits November 4, 2020 19:52
We decorate the existing metadata cache of each entity manager with a
PHP Array Cache when not in debug mode. That cache is warmed up by
getting all the metadata for all entities.
Since metadata is not supposed to be discovered at runtime, the fallback
cache, which is the one configured through this key, is never supposed
to be used. There is no point in configuring it.
Copy link
Member

@greg0ire greg0ire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed new commits with explanations that might be completely wrong, please review and amend them if necessary.

@ostrolucky ostrolucky merged commit ae25798 into doctrine:master Nov 7, 2020
@stephanvierkant
Copy link

It isn't clear to me what I've to change in my application and I'm not the only one: https://stackoverflow.com/questions/64741823/symfony-4-4-metadata-cache-driver-configuration-key-deprecation-notice

Can someone explain why this change was needed and how we should replace metadata_cache_driver? If I understand, I can update the Symfony docs (if needed).

@ostrolucky
Copy link
Member

metadata_cache_driver configuration needs to be removed. Change is needed because defining own metadata_cache_driver is useless from now on.

$phpArrayCacheDecoratorServiceId = $decoratedMetadataCacheServiceId . '.php_array';
$phpArrayFile = '%kernel.cache_dir%' . sprintf('/doctrine/orm/%s_metadata.php', $entityManagerName);

$container->register(DoctrineMetadataCacheWarmer::class)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ossinkine actually this is not working properly for multiple entity managers. I just tried it on one of my bigger projects that uses 2 managers.

Since DoctrineMetadataCacheWarmer::class is the service id it will only work for the last manager and overwrite any previous definitions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add PhpArrayAdapter to cache metadata
7 participants