Skip to content
This repository has been archived by the owner on Feb 6, 2020. It is now read-only.

Performance - Abstract factory request cache #226

Conversation

fhein
Copy link

@fhein fhein commented Jan 12, 2018

Work in Progress ...

This patch provides caching for abstract factory requests, so canCreate will be called only once on consecutive requests for the same service.

This feature can be turned on and off via config or anytime during the life time of the service manager. If turned off the cache gets unset.

Recommended implementations of abstract factories should have an invariant canCreate method. Same request, same answer the life time through. But if users want to employ abstract factories where canCreate answers can change during life time, this feature has to be turned off.

There is currently no benchmark in place which provides meaningful information about the real life performance gain. Such a benchmark should assume some cost for canCreate. I will prepare.

What you can see using the current FetchNewServiceViaConfigAbstractFactoryBench is the small amout of overhead this feature introduces for cache administration.

weierophinney and others added 30 commits March 1, 2017 16:08
removed duplicate allow_failures
Updated packages in composer to latest stable version and PHP requirements
changed to PHP ^7.1
Updated suggestion in composer.
Those optimizations target improving OPCODES.
…nternal-functions

Import PHP internal functions
replace count() usage to empty() when possible
fhein added 3 commits January 12, 2018 17:06
will be called only once on consecutive requests for the same service.

This feature can be turned on and off via config or at anytime during
the life time of the service manager. If turned off the cache gets
unset.
@fhein
Copy link
Author

fhein commented Jan 12, 2018

Reconsidered this one. The idea is good. The implementation is bullshit. We already have a 'hasCache'. It's called $this->factories. On the other side, the hasNotCache applies to all unknown services, not only for services, which abstract factories do not know about.

Changed that to cache abstractfactories as factories and unknownServices caching now covers all requests.

fhein added 12 commits January 13, 2018 00:03
addInitializer, addDelegator, mapLazyService.

Configure: replaced (isset($config['xyz']) guards with !
empty($config['xyz']) guards. This has no negative performance impact,
but is more precisely what we
want to know.

Added BenchAsset\DelegatorFactoryFoo for performance tests. Added some
tests to setNewServicesBench.php.
Reintroduced reference to Tarjans Algorithm again. Added simple test for
failing behaviour. Error was detected while adding tests to increase
code coverage. One of the parts not covered was bad.
will be called only once on consecutive requests for the same service.

This feature can be turned on and off via config or at anytime during
the life time of the service manager. If turned off the cache gets
unset.
@Ocramius
Copy link
Member

Ocramius commented Jan 16, 2018 via email

@fhein
Copy link
Author

fhein commented Jan 16, 2018

Abstract factories wouldn't have to be idempotent. Idempotency is a funky word. As I see it here, the service manager would get idempotent in a sense that a request which can get resolved to an abstract factory would be resolved to the same abstract factory when the same name gets requested again.

If the abstract factories are designed to produce the same service for a particular name requested (i.e, are idempotent) this feature would have significantly positive performance impact. I checked several real life scenarios. Most of them use this 'pattern'.

I'd not recommend to use abstract factories which change behaviour at runtime at all. Problems which may arise can be quite difficult to track down.

On the other hand, the service manager explicitly supports (there is a test for it) to register the same abstract factory twice. I do not completely understand how it would be accomplished to let the the first reference's canCreate return false and the second return true. But that this feature is supported and tested suggests somehow, that there are use cases for abstract factories, which are not idempotent. I find it difficult to imagine what these use cases are.

I'd vote for integration of the abstract factory cache and an option to turn it off for bc and for particular use cases relying on non-idempotent abstract factories.

@fhein
Copy link
Author

fhein commented Jan 17, 2018

I leave this open for discussion. Implementation is outdated. Too much things to manually merge. If the feature can be agreed on, I'll reimplement.

@Ocramius
Copy link
Member

Ocramius commented Jan 17, 2018 via email

@fhein
Copy link
Author

fhein commented Jan 17, 2018

Not if configurable and default is bc.

@Ocramius
Copy link
Member

Not if configurable and default is bc.

Let's just introduce a BC break, document it and delay for 4.0.0 instead. A configuration flag just complicates things.

@fhein
Copy link
Author

fhein commented Jan 17, 2018

Do you think so? 'enableAbstractFactoryCache' => true, if people want it, does not seem to be to overcomplicate to me. (?)

We could get some performance measures from practical use to justify further support of that feature.
If it is not worth it, it could be removed with 4.0.0 without bc break. But I believe, the feature will proof its valuable.

@Ocramius
Copy link
Member

@fhein it is kinda problematic to introduce a flag that just serves as a filler until the next release is out.

@fhein
Copy link
Author

fhein commented Jan 17, 2018

If we can agree on the feature and it would get default on without configuration option (abstract factory idempotence), then the flag would not harm if present in implementation.

We could issue a deprecation note stating that the flag is ignored.

@fhein
Copy link
Author

fhein commented Jan 19, 2018

This feature will speed up non-shared service creation only, of course, because shared services produced by an abstract factory are cached already. So it may be not on the 'hot path'. I think, not-so-hot pathes should be empowered as well as long as hot pathes don't suffer from doing so.

@fhein
Copy link
Author

fhein commented Jan 22, 2018

@Ocramius: Service Manager caches abstract factories and other factories. So this feature is not a bc break.

@fhein
Copy link
Author

fhein commented Jan 29, 2018

This one is obsolete.

@fhein fhein closed this Jan 29, 2018
@fhein fhein deleted the PERFORMANCE-AbstractFactoryRequestCaching branch January 30, 2018 03:18
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants