hey Larry,

the current approach is compatible with Symfony - David Negrier (among 
others) were very concerned with this, and he did in fact build a Symfony 
bridge:

https://github.com/thecodingmachine/service-provider-bridge-bundle

I understand this does not enable containers like Symfony or PHP-DI to 
apply the kind of optimizations they apply to their own configuration - but 
the
declarative configuration they use is also much more in need of 
optimization than some of the simpler code-based configuration approaches. 
These
optimizations exist because these DI containers need them.

Anton Ukhanev (XedinUnknown) previously wrote this:

> I really like the way SP is right now, because I think that currently it 
addresses all concerns that are related to providing extendable services. I 
don't think that
> containers themselves, or how they are consumed, is very much the scope 
of SP. For example, container cannot be compiled themselves, because their
> members are not enumerable. But Service Providers are, because multiple 
service providers can be merged into one, and then combined definitions
> can be enumerated and cached separately, which will save speed when the 
definitions have to be resolved by a container. 

https://github.com/container-interop/service-provider/issues/51#issuecomment-642644119

there are pros and cons to compilation, just as there are pros and cons to 
any approach taken by any other container types.

note that service providers can be integrated in both directions - if the 
Symfony container didn't want to consume standard service
providers, it could still make it's own code-generated container produce a 
service provider, which you could then plug in somewhere else.
other projects in the community might benefit from Symfony's compiled 
containers that way, if they wanted.

I would also point out that the performance of individual service providers 
would depend on how they're implemented - if you wanted
to hand-write switch-statements, you can do that, and get equal performance 
to Symfony. If you can figure out a way that's even faster,
you are free to do that too. :-)

so yes, the individual service provider sets the theoretical speed limit - 
that would be true for any consuming container, not just Symfony's.

so I don't think it makes sense to paint the situation as though standard 
service providers in this form would be useless to Symfony?

Rasmus

On Friday, January 12, 2024 at 6:35:46 PM UTC+1 Larry Garfield wrote:

> On Fri, Jan 12, 2024, at 4:44 PM, Rasmus Schultz wrote:
> > Dear Figs :-)
> >
> > I've been hard at work these past couple of months, since I became 
> > interested in the Service Provider PSR proposal again.
> >
> > I've spent many nights and have read through every issue and comment on 
> > the issue tracker, and many old discussions here on the group, going 
> > back as far as 6-7 years.
> >
> > I eventually ended up writing a proper draft for the PSR itself, as 
> > well as a meta-document. And the updated proposal features optional 
> > dependency enumeration, which you can read more about in the new 
> > documents.
> >
> > You can find the new documents here:
> >
> > https://github.com/container-interop/service-provider
> >
> > This is a call for participation! I'd like to invite you to read the 
> > drafts, comment on open issues, and contribute to discussions.
> >
> > Note that the "Issues" tab on the Github page is intended for issues 
> > with the documents themselves, while the "Discussion" tab should be 
> > used to propose ideas and discuss implications. ("there is a problem 
> > with the spec" is an issue, while "how about this cool idea" is a 
> > discussion.)
> >
> > I worked hard on this, and I'm taking the lead on another push to bring 
> > this proposal to fruition, so I really hope some of you will take an 
> > interest. Let's make it happen! :-)
> >
> > Thank You.
> >
> > Regards,
> > Rasmus Schultz
>
> First off, thank you for resurrecting this topic. I argued at the time of 
> PSR-11 that the registration side was at least as important as the 
> extraction side, and while I eventually came around on PSR-11 doing just 
> the extraction part, I still believe the registration side is just as 
> important.
>
> That said, I don't think the current approach is viable. I appreciate the 
> simplicity argument for it over some of the alternatives, but it has one 
> rather large flaw: It's incompatible (as far as I can tell) with compiling 
> or optimizing containers.
>
> To be very brief (more for the audience than for Rasmus, who I'm sure 
> knows this already), some containers do all registration at runtime. In 
> that case, having every provider return an array of closures works well 
> enough. Others collect the service and dependency information once and 
> code-generate a file or files that are used at runtime, with all the 
> information pre-computed so the registration process does not need to run.
>
> The quality of compiled container output varies widely, but all of them 
> are substantially faster than a runtime container. The best use generated 
> match() statements, which benchmarks show are faster than even a chain of 
> if-statements and, likely, an array lookup to a closure. In the ideal case, 
> you end up with generated code like:
>
> public function get(string $service): mixed
> {
> return $this->cache[$service] ??= match($service) {
> \App\A::class => new \App\A(),
> \App\B::class => new \App\B($this->get(\App\A::class)),
> \App\C::class => new \App\C($this->get(\App\A::class), 
> $this->get(\App\C::class), 'some-constant'),
> default => throw new Exception(...);
> };
> }
>
> (You could actually do better than that, but I'm trying to keep it simple.)
>
> The problem is, Closures cannot be serialized. That means the factory 
> approach as presented is incompatible with a compiled container; the only 
> option would be to do some kind of AST parsing of the closure and 
> regenerate its code, which... ew.
>
> So standardizing registration on a mechanism that is incompatible with 
> high-performance containers seems... not great. I realize the alternatives 
> with standard file formats have their own challenges, which is why they 
> haven't been done yet.
>
> I think probably the best option would be to effectively standardize 
> something along the lines of Symfony's compiler passes, with a more modern 
> API design. Pass a ContainerBuilder to a series of objects with some 
> standard interface for defining and modifying service entries. With the 
> data then in-memory in an abstracted form, it could be used at runtime or 
> compiled, as the container implementation prefers.
>
> Part of me wants to build such a compiler-pass system on top of PSR-14, 
> since it's virtually the same model. (And that kind of "registration pass" 
> was an explicit design target of PSR-14.) It could probably be done in a 
> PSR-14-optional way.
>
> --Larry Garfield
>

-- 
You received this message because you are subscribed to the Google Groups "PHP 
Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to php-fig+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/e99086f6-de05-4010-8f46-c3e3f176f344n%40googlegroups.com.

Reply via email to