laravel / octane

Supercharge your Laravel application's performance.
https://laravel.com/docs/octane
MIT License
3.78k stars 296 forks source link

Looking forward to support for Swoole coroutines #765

Closed clemask closed 1 year ago

clemask commented 1 year ago

We really look forward to Octane supporting Swoole coroutines, which will bring higher performance and solve more business scenarios. We hope the official will include this in the roadmap as soon as possible.

taylorotwell commented 1 year ago

Feel free to work on it! šŸ‘

clemask commented 1 year ago

Octane is a great project that is pushing Laravel in a new direction in the realm of the internet, making Laravel more powerful. However, there seem to be some issues with the way it's being handled in certain aspects. Octane's support for Swoole has excited many developers, including myself, envisioning a strong combination of Laravel's ecosystem with Swoole's coroutine advantages.

One crucial point that is not clearly stated in the official documentation is the inability to use Swoole's coroutine. This omission is significant because developers might unknowingly configure coroutine parameters, expecting Octane to work seamlessly with Swoole's coroutine features. However, Octane does not disable the creation of Swoole services with coroutine parameters, leading to subtle issues in the production environment. Problems like network connections being used by other coroutines and issues with Monolog log cycling detection can arise. In the end, developers are forced to disable coroutines as a quick solution, which is a severe incident.

I hope the official team promptly considers adding coroutine support to their roadmap. It's a fantastic feature that not only enhances Laravel but is also crucial for the broader PHP ecosystem.

driesvints commented 1 year ago

I hope the official team promptly considers adding coroutine support to their roadmap.

This isn't a trivial thing to do. Right now we don't have the time to work on this ourselves but we'd love to see PR's kickstarting this.

binaryfire commented 12 months ago

Hey @driesvints, are you familiar with @themsaid's talk from Laracon 2021 on how Swoole coroutines could be integrated into Octane? This is the timestamp: https://youtu.be/-l8o4KMaS4c?feature=shared&t=1792

That change has already been merged into Swoole core: https://github.com/swoole/swoole-src/pull/4330

I'm not sure how difficult it would be to implement, but it'd increase Laravel's performance by a whole order of magnitude.

driesvints commented 12 months ago

Welcoming prs šŸ‘

huangdijia commented 11 months ago

If you want octane to support coroutine, you must first make database, redis, etc. support connection pooling.

binaryfire commented 11 months ago

I guess the problem is Laravel supports a lot of DB and cache backends and itā€™d be hard to implement pooling for them allā€¦

@taylorotwell @driesvints @nunomaduro Would the core team be interested in having pooling for a select few drivers? Maybe just MySQL and Redis to start. Itā€™d mean coroutines could only be enabled when using those drivers, but Hyperf can handle 100k req/second. Even if coroutines ā€˜onlyā€™ bumped Laravelā€™s concurrency to 10k-20k, thatā€™d be nuts and create some serious buzz. Thatā€™s faster than Nodeā€¦

FYI @huangdijia is a key Hyperf contributor: https://github.com/hyperf/hyperf/commits/master. He might be willing to help if you guys want to move ahead.

taylorotwell commented 11 months ago

@binaryfire I review all PRs - merging just depends on added complexity / maintenance burden. šŸ‘

fannyfan414 commented 11 months ago

It would be amazing feature for highload apps!

foremtehan commented 6 months ago

Can this be related? šŸ‘€

image

binaryfire commented 6 months ago

Can this be related? šŸ‘€

No thatā€™s not related. Running a few tasks concurrently is different to workers that can properly handle multiple requests per second, which requires db connection pooling etc. I donā€™t think thereā€™s much interest from the core team in increasing Laravelā€™s performance beyond the current Octane implementation, which only helps by keeping the app booted in memory. It doesnā€™t use Swoole coroutines at all.

If you want to handle 40k - 100k req/s in real life workloads instead of Octaneā€™s 500-ish, youā€™ll need to either run a bunch of Octane instances behind a load balancer, or look at a proper coroutine framework like Hyperf. The performance difference is night and day.

People who say ~500 req/s is enough just arenā€™t building certain kinds of apps. Eg. a log ingestion app, API gateways etc. Even a core team member has written articles about adding Go to a Laravel app stack to handle endpoints which receive high numbers of requests, which clearly demonstrates Laravelā€™s performance limitations.

Shipping more features seems to be a higher priority than a major upgrade to performance. This kind of change, and the refactoring that would be required (eg. adding db connection pooling) wonā€™t ever come from a third party PR. It would need be be driven by the core team.

Hyperf is heavily inspired by Laravel so there are plenty of code references there the core team could look at.

huangdijia commented 6 months ago

Can this be related? šŸ‘€

No thatā€™s not related. Running a few tasks concurrently is different to workers that can properly handle multiple requests per second, db connection pooling etc. I donā€™t think thereā€™s much interest from the core team in increasing Laravelā€™s performance beyond Octane, which only helps by keeping the app booted in memory.

So if you want to handle 40k - 100k req/s in real life workloads instead of Octaneā€™s 500-ish, youā€™ll need to either run a bunch of Octane instances behind a load balancer, or look at a PHP framework like Hyperf.

People who say 500 req/s is enough just arenā€™t building certain kinds of apps. Eg. a log ingestion app, an API gateway etc. Even a member of the core team has written articles about adding Go to a Laravel app stack to handle endpoints which receive high numbers of requests, which is saying something.

Shipping more features seems to be a higher priority than any major upgrades to performance. This kind of change and the refactoring (eg. adding db connection pooling) wonā€™t come from a third party PR. It would need be be driven by the core team.

The design idea of octane is still based on fpm,To get better performance, you need to redesign

SMFloris commented 6 months ago

Managed to get Laravel working with multiple Swoole coroutines in one process today. I still have allot of cleaning up to do before a PR, but I am confident it could be ok. Currently we got it working for a custom Kernel that processes sqs jobs for aws lambda, but to get it working for the http kernel is trivial. By Friday, I'll have it up and running in multiple processes as well (probably already works, but needs further testing).

@taylorotwell , @nunomaduro , is this still of interest?

fannyfan414 commented 6 months ago

Managed to get Laravel working with multiple Swoole coroutines in one process today. I still have allot of cleaning up to do before a PR, but I am confident it could be ok. Currently we got it working for a custom Kernel that processes sqs jobs for aws lambda, but to get it working for the http kernel is trivial. By Friday, I'll have it up and running in multiple processes as well (probably already works, but needs further testing).

@taylorotwell , @nunomaduro , is this still of interest?

This will be the most long-awaited and amazing feature for all highload Laravel projects!

SMFloris commented 6 months ago

This kind of change, and the refactoring that would be required (eg. adding db connection pooling) wonā€™t ever come from a third party PR. It would need be be driven by the core team.

Interestingly enough I did run into this today with testing multiple processes with multiple coroutines each. Database pooling is kinda of a solved problem upstream in openswoole at least (I am using openswoole atm).

https://github.com/openswoole/openswoole/blob/master/example/src/Coroutine/MySQLClientPool.php

Also available: Redis, Postgres.

Going to implement a mysql and redis pool next, which seems to be the last step I need to get the whole thing running blazingly fast. It is actually quite amazing how fast everything is.

binaryfire commented 6 months ago

@SMFloris Nice! Iā€™d suggest using Swoole rather than Openswoole for testing - all Swoole development happens there. The whole ā€œsecurityā€ thing was blown completely out of proportion by the Openswoole guy who now just repackages Swoole by himself to try and steal some brand recognition.

Also one of the core Swoole maintainers (@deminy) has said heā€™s happy to answer questions to help: https://github.com/swoole/swoole-src/pull/4330#issuecomment-1837271923

Re: the performance difference - yeah Iā€™ve used Hyperf for several high load projects and the difference is night and day. It can handle approx 40x more req/s than Laravel Octane thanks to being built with coroutines from the ground up. Pretty comparable to Go. Companies are building game server backends with it, which is pretty nuts for a PHP framework.

IMHO properly implementing coroutines in Laravel would open up the framework to a whole group of devs who would never have considered PHP otherwise.

@huangdijia is a core Hyperf contributor and might be willing to review your PR too

Iā€™d also suggest posting some benchmarks with your PR to show the performance benefits.

SMFloris commented 6 months ago

@binaryfire thanks for your input! Will use Swoole going forward.

I was just thinking that the level of speed is at the level of Go as well.

What I'll do after implementing the pooling connections as well (I'm trying not to hack to much, doing things the Laravel way as much as possible) is that I'll create a repo with a docker compose so that anyone can run the benchmark easily.

What sort of things would be nice to benchmark? I'm thinking of a route that simply returns an OK status and a route that does some inserts or reads from the database. I personally want to compare: simple Laravel behind nginx, laravel octane as it currently is and laravel octane with all the bells and whistles from coroutines.

SMFloris commented 5 months ago

This weekend I made some headway;

Turns out there are allot more stuff to wire together than I thought initially.

evan361425 commented 5 months ago

Why not using coroutine hooks?

It don't need to change code base, just hooking the PHP C code interface. We can enable it by calling \OpenSwoole\Runtime::enableCoroutine(); before worker start.

I've tried it as issue #906 mentioned but encountered some issues in binding process.

xwiz commented 3 months ago

@SMFloris can you possibly push your changes so another person can pick up from where you are at or assist.

clemask commented 1 month ago

@SMFloris Is there any new progress?

osbre commented 1 month ago

To anyone being passionate about this feature, I recommend reading https://openswoole.com/article/isolating-variables-with-coroutine-context.

As I see it, simply flipping the switch to do Runtime::enableCoroutine and implementing connection pooling would result in a buggy behaviour throughout the app, due to the number of static variables that would essentially get shared between all of the coroutines. You can look at how Octane currently has to reset the state of the container inside each worker before processing a request.

There appears to be an architectural problem with static variables which wouldn't let us use coroutines as of right now. All of that state which is being reset has to be stored in the coroutine context rather than globally.

I'll also look into this later.

Upd: Not just static variables, many of the container instances have to be retrieved from the coroutine state rather than just reset.

huangdijia commented 1 month ago

https://laravel-hyperf.com/ @binaryfire

clemask commented 1 month ago

https://laravel-hyperf.com/ @binaryfire

Can it be migrated safely, easily and quickly?

harryqt commented 1 month ago

No yet. The project is at alpha stage.

huangdijia commented 1 month ago

https://laravel-hyperf.com/ @binaryfire

Can it be migrated safely, easily and quickly?

Currently the laravel ecosystem is not supported, such as horizon, telescope, etc.

binaryfire commented 1 month ago

No yet. The project is at alpha stage.

Hyperf is a completely different framework. The starter project Deeka linked to is just arranged in a way thatā€™ll be familiar to Laravel devs. Directory structure etc.

You canā€™t swap out Laravel for Hyperf in an exisiting project. It would require significant rewriting.

Cluster2a commented 1 month ago

No yet. The project is at alpha stage.

Hyperf is a completely different framework. The starter project Deeka linked to is just arranged in a way thatā€™ll be familiar to Laravel devs. Directory structure etc.

You canā€™t swap out Laravel for Hyperf in an exisiting project. It would require significant rewriting.

We migrated a module from our Laravel-Monolith to Hyperf, to run it as a separate Service. We only had to setup the bootstrapping (Services/middlewares and so on). For the business logic, we copied over the models, the controllers and everything was working almost out of the box.

binaryfire commented 1 month ago

We migrated a module from our Laravel-Monolith to Hyperf, to run it as a separate Service. We only had to setup the bootstrapping (Services/middlewares and so on). For the business logic, we copied over the models, the controllers and everything was working almost out of the box.

Yeah it's great for microservices. We have several high traffic services using Hyperf - the performance difference is massive. The framework was heavily inspired by Laravel and uses a forked coroutine-friendly version of Eloquent so it's easy for Laravel devs to pick up. Things like models are easy to move over but there are many additional considerations when building complex apps eg. the way Context works.

Not everything in the ecosystem can be ported over eg Livewire: https://github.com/hyperf/hyperf/issues/5517. We've gone all in on Livewire so unfortunately that makes Hyperf a no-go for our core apps. Also there's no first-party auth package since the framework is geared towards microservices. But it's our first choice for anything we have to break out.

clemask commented 1 month ago

https://laravel-hyperf.com/ @binaryfire

Can it be migrated safely, easily and quickly?

Currently the laravel ecosystem is not supported, such as horizon, telescope, etc.

I donā€™t know the usage of Horizon and Telescope. Compared with those using Laravel, it should be relatively low. It would be very exciting if it could support the migration of Laravel projects. @huangdijia

huangdijia commented 1 month ago

I donā€™t know the usage of Horizon and Telescope. Compared with those using Laravel, it should be relatively low. It would be very exciting if it could support the migration of Laravel projects. @huangdijia

Welcome to learn about and use Hyperf. It can be accessed via the documentation (https://hyperf.wiki) to Learn about it.

albertcht commented 1 month ago

Hello everyone,

I'm the creator of the Laravel Hyperf project. This project is currently in its final stage before the first dev release. I've migrated most components from Laravel to make them coroutine-friendly while striving to maintain a similar development experience to Laravel.

From my perspective, implementing full coroutine support in the Laravel framework presents significant challenges for several reasons:

  1. Laravel's components weren't designed with coroutines in mind. This means all states would need to be isolated within the coroutine context, as @osbre mentioned. Laravel Octane's approach of resetting states after each request doesn't address this fully. For instance, if a singleton object needs to be shared across coroutines, the reset mechanism becomes ineffective.

  2. Swoole introduced a max_concurrency setting (see here) to enable Laravel Octane to support coroutines with limited restrictions. When max_concurrency is set to 1, the worker won't accept new requests until the current one is completed. While this ensures coroutine safety and allows for state resets, it essentially makes coroutines an alternative concurrency feature in Laravel without improving QPS performance, as a worker can still only handle one request at a time.

  3. Even if Laravel Octane were to support full coroutines in the future, it would necessitate significant breaking changes in Laravel components. All states would need to be safely stored using context, which would have a substantial impact on the third-party ecosystem.

The complexity of migrating from Laravel to Laravel Hyperf depends on the extent of state management and third-party packages used in your project. If you're considering migration, keep in mind:

  1. Laravel Hyperf is a distinct framework, so a cost-free migration process is unrealistic.
  2. Laravel packages can't be used directly in Laravel Hyperf due to coroutine safety issues.
  3. The Laravel Hyperf ecosystem is still in its early stages. If you require specific Laravel packages that haven't been migrated to Laravel Hyperf yet, you may need to do it yourself.

In conclusion, I highly recommend trying Laravel Hyperf for new projects with intensive I/O requirements. However, if you're planning to migrate an existing Laravel project, be prepared for necessary modifications and consider the ecosystem implications carefully.

For current Hyperf users, you can also refer to firendsofhyperf for some useful packages.

foremtehan commented 1 month ago

Even if Laravel Octane were to support full coroutines in the future, it would necessitate significant breaking changes in Laravel components. All states would need to be safely stored using context, which would have a substantial impact on the third-party ecosystem.

No need to introduce breaking changes, They need to fork laravel/framework and continue developing the fork version. @themsaid

fakharksa commented 1 month ago

Trying to integrate Swoole into PHP-FPM-based (PHP-) Frameworks (like, Laravel) is entirely (and, philosophically) a wrong direction to go.

People who want to enjoy modern (CSP based) Asynchronous PHP-Programming will need to shift the paradigm of their thought Process from PHP-FPM based frameworks to "Asynchronous Programming Paradigm".

They (PHP-FPM and Swoole) both utilise entirely different OS-concepts and entirely different programming concepts, and entirely different Application Architectures. Swoole is just like Go, VertX, Netty, Erlang, Tornado etc.