+------------------------------------------------------------+
| Process |
| +--------------------------------------------------------+
| | Threads (OS/User) |
| | +----------------------------------------------------+
| | | Coroutines |
| | | + - - - - - - - - - - - - - - - - +
| | | | ┌ Fiber (with stack, yield anywhere) |
| | | + |
| | | | └ Generator (stackless, top-level yield) |
+---+---+---+------------------------------------------------+
- are preemptively scheduled by the OS (external scheduler is allowed to interrupt execution of a task)
- may yield voluntarily to suggest to interrupt execution of its task
- run in parallel (as long as there are not more active threads than cores)
- run in percieved random order
- are cooperatively scheduled by the program
- must suspend themselves to yield execution to other tasks
- run concurrently, i.e. only one at any given time
- run in deterministic order (from the POV of the program)
- do not force a specific return type for functions declaring interruption points
- Generator
$g = (function() : Generator { yield; return 123; })();
- Fiber
$f = new Fiber(function() : mixed { Fiber::suspend(); return 123; });
- Generator
- have a full function call stack
- can suspend their execution from any nested function call,
compared to Generators'
yield
only suspending from top level- Generator
// this yield of g2 only bubbles up to // the program because g1 decides to do so function g2() : Generator { yield 2; } // this yield of g1 is the actual and // only true interruption point function g1(Generator $sub) : Generator { yield from $sub; } foreach (g1(g2()) as $y) { // ... }
- Fiber
function s(callable $f = null) { Fiber::suspend(); if ($f) $f(); } // two "yields" at different function call depths, // without any involvement of the actual fiber function function f() { s(s(...)); } $f = new Fiber(f(...)); for ($f->start(); !$f->isTerminated(); $f->resume()) { // ... }
- Generator
- can suspend their execution from any nested function call,
compared to Generators'
Threads | Generators | Fibers | |
---|---|---|---|
available in PHP | 7.2 - 8.0 [1] | 5.5+ | 8.1+ |
model | parallel | concurrent | concurrent |
complexity | high | awkward | reasonable |
best used for | parallel computation | dynamic iterators | asynchronous I/O |
are not | a hammer like PHP | comprehensible as coroutines [2] | async/await, yet |
[1] ext-parallel with thread safe PHP, http://pecl.php.net/package/parallel
[2] https://www.npopov.com/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html