Upgrade to Pro — share decks privately, control downloads, hide ads and more …

From Generator to Fiber the Road to Coroutine in PHP

Albert Chen
December 20, 2022

From Generator to Fiber the Road to Coroutine in PHP


Albert Chen

December 20, 2022

More Decks by Albert Chen

Other Decks in Programming


  1. 02 Blocking and Async I/O in PHP Outline 01 I/O

    Models in Linux 03 What is Generator? 04 What is Fiber in PHP 8.1? 05 How to use Async I/O with Coroutine? 07 Q&A 06 Coroutines in Swoole
  2. Read/Write Read/Write (O_NONBLOCK) I/O Multiplexing (select/poll/epoll) AIO I/O Models in

    Linux Simplified Matrix of Linux I/O Models Blocking Non-Blocking Synchronous Asynchronous (https://developer.ibm.com/articles/l-async)
  3. select poll epoll Data Structue Array Link List Hash Table

    Big O O(n) O(n) O(1) FD Limit 1024 (x86) 2048 (x64) Unlimited Unlimited I/O Multiplexing I/O Multiplexing in Linux
  4. Blocking I/O in PHP All I/O functions in PHP are

    born to be synchronous Easy for developers to understand Less-efficient for utilization of CPU usage
  5. sleep file_get_contents shell_exec end Blocking I/O in PHP 1s 3s

    3s process idle + + process idle process idle 7s =
  6. 1s worker 1s worker 1s worker Blocking I/O in PHP

    If one request takes 1s in I/O waiting Each worker can handle only one request and the same time Concurrency in PHP depends on worker numbers Context switch between processes are expensive! request request request
  7. Asynchronous I/O in PHP The simplest but worst-performant solution in

    PHP spatie/async package (needs pcntl and posix extensions)
  8. Asynchronous I/O in PHP The simplest but worst-performant solution in

    PHP spatie/async package (needs pcntl and posix extensions) worker process process fork fork
  9. Asynchronous I/O in PHP Async I/O Extensions in PHP ext-event:

    libevent wrapper ext-ev: libev wrapper ext-uv: libuv wrapper Both ReactPHP and Amp support these extensions as event-loop drivers
  10. Asynchronous I/O in PHP Event Loop Event Queue Stream Stream

    Stream Stream Stream Event Loop callbacks
  11. Generator Supported from PHP 5.4 Generator provides an easy way

    to implement simple iterators Generator allows you to write code that uses foreach to iterate over a set of data without needing to build an array in memory Generator can yield as many times as it needs to provide the values to be iterated over (From official PHP manual)
  12. Generator Generators, also known as semi-coroutines, are a subset of

    coroutines Coroutines can control where execution continues immediately after they yield, while Generators cannot, instead transferring control back to the generator's caller The yield statement in a generator does not specify a coroutine to jump to, but rather passes a value back to a parent routine (From Wikipedia)
  13. Generator Two Way Data Transfer in Generator yield1 ret1 yield2

    ret2 NULL the first var_dump in gen the var_dump of the ->send() again from within gen the return value of ->send() (https://www.npopov.com/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html)
  14. Fiber New feature in PHP 8.1 Submitted and developed by

    Amp Unlike stack-less Generators, each Fiber has its own call stack, allowing them to be paused within deeply nested function calls Execution may be interrupted anywhere in the call stack using Fiber::suspend() Once suspended, execution of the fiber may be resumed with any value using Fiber::resume() (From official PHP manual)
  15. Fiber Both ReactPHP and amp(3.0 beta) support Fiber now A

    comprehensive coroutine rather than semi-coroutine Eliminates yield statement for coroutines Fiber doesn't turn your code into non-blocking magically, traditional blocking code has to be rewritten for asynchronous I/O Help not too much for most of developers Fiber provides only bare minimum required to allow user code to implement full-stack coroutines in PHP Fiber doesn't support Preemptive Scheduling yet
  16. Questions What's the difference between Asynchronous and Coroutine? What's the

    difference between Generator and Fiber? How to turn Blocking I/O stream turning into Non-Blocking? What is Event Loop? Is it required for Asynchronous? What's the benefits of Coroutine? Is Asynchronous a must for Coroutine? How to make built-in Blocking I/O functions Asynchronous? Can Asynchronous I/O be integrated with traditional Blocking I/O environment? (e.g. PHP-FPM)
  17. Coroutine in Swoole Basic Usage start coro 1 start to

    resume 1 @1 resume coro 1 @1 start to resume 1 @2 resume coro 1 @2 main
  18. Coroutine in Swoole Fatal error: Uncaught Exception: 12.5ms end in

    xxx Stack trace: #0 {main} thrown in xxx Preemptive Scheduling
  19. Coroutine in Swoole Channel [coroutine 3] int(0) [coroutine 2] -

    0 [coroutine 3] int(1) [coroutine 2] - 1 [coroutine 3] ......
  20. Coroutine in Swoole Swoole implements its full coroutine features Built-in

    Blocking I/O functions can be replaced to Non-Blocking I/O automatically if hook flags are set Swoole supports Preemptive Scheduling for CPU-bound tasks Swoole Provides CSP Model for Coroutine Communications like in GoLang Yields and resumes take place behind the scenes for I/O functions switching
  21. Q&A