woohoolabs / harmony

A simple and flexible PHP middleware dispatcher based on PSR-7, PSR-11, and PSR-15
MIT License
164 stars 16 forks source link

Lazy Loading? #24

Closed mattsah closed 5 years ago

mattsah commented 5 years ago

Is there a way to register middlewere to be lazy loaded by providing a PSR-11 container?

kocsismate commented 5 years ago

Hi,

No, Harmony doesn't support this functionality yet.

The reason is that generally all middleware gets executed at some point during the request-response lifecycle (if this is not the case then conditional middleware can also help). Furthermore, if the dependencies of a middleware are too heavy to instantiate in advance then the middleware could take the DI container instead and instantiate these dependencies just in time.

Could you tell me more about your use-case? So I could learn more why this functionality is useful for you. :)

mattsah commented 5 years ago

While I realize many middleware are not particularly heavy, it's pretty common that middleware may return early because they take some decisive decision. For example, my "firewall" middleware is registered pretty early in the stack. If an IP address is blocked, it returns forbidden immediately -- all the middleware after that are not executed and therefore their instantiation was for naught along with all their additional dependencies.

This may not seem like a big deal, but if you have an API handling thousands of requests if 10% of those return early for some obvious reason like an IP being blocked or the request not being authorized, it can add up.

kocsismate commented 5 years ago

This may not seem like a big deal, but if you have an API handling thousands of requests if 10% of those return early for some obvious reason like an IP being blocked or the request not being authorized, it can add up.

Yes it's true that it adds up but I think the performance gain is minimal given object instantiation in PHP is very cheap.

In order to test this statement I made a small benchmark that is available here: https://3v4l.org/j301h If I got it right then instantiating 1 million objects only takes 44 ms (and it is just a simple 3v4l server).

That said, I am not convinced that adding support for lazy loading of middleware is worth the effort. My view can be probably changed if there are other good reasons other than performance optimization.

mattsah commented 5 years ago

I don't doubt that object instantiation in itself is fast. I'm a little less convinced that object instantiation through a dependency injector, with various possible sources for dependency configuration information -- including potentially database queries, is.

Anyhow, I mostly wanted to make sure I wasn't missing some way to do this inadvertently, if it's not available and there's no plan to support it, then that answers my question and I can move along to something that does.

Thanks anyhow.

kocsismate commented 5 years ago

OK, I see your point. But still, I don't plan to support this feature currently. If I remember correctly, Zend Expressive does support it.

Thanks for the question by the way. Have a nice day!