Conversation
Haitao Lv added 2 commits
March 31, 2018 00:31
Haitao Lv added 3 commits
March 31, 2018 18:16
| EG(vm_stack_top) = fiber->stack->top; | ||
| EG(vm_stack_end) = fiber->stack->end; | ||
| EG(vm_stack) = fiber->stack; | ||
| EG(vm_stack_page_size) = fiber->stack_size; |
As much as i love the idea of stackless (in terms of C stack) fibers i think that they are not reliable enough to be accepted at this time. In order to make them work in all situations it would require a "Stackless PHP" that executes a lot of nested function calls in the main VM loop. I played around with that idea in (https://github.com/stackless-php/php-src) and tried to make it work in ReflectionFunction::invoke() by using a continuation function. Such an approach might work for function calls but it requires massive changes to the code of the function and opcode handlers (DO_ICALL etc.) to make it work. Iterators and Generators are a different story, they will be a lot harder to adjust for stackless execution...
Comparing both fiber implementations yields (no pun intended) the following properties:
| Property | Stackless Fiber | Native Fiber |
|---|---|---|
| 1 - Minimum Memory Usage | VM stack only (4 KB) | VM & C stack (4 KB + 4 KB) |
| 2 - Supported Architecturs | any platform supported by compiler | only x86 systems at this time |
| 3 - Yield in Internal Function | unsupported | supported |
| 4 - Yield in Iterator | unsupported | supported |
Stackless fiber use less memory and are not platform-dependend (1 & 2) which makes them very portable and efficient. They do however lack support for anything that involves internal function calls (3) including opcode handlers (4, e.g. foreach loop).
Native fibers are very platform-dependend (2) and use more memory because they do need to allocate a C call stack (1). While memory allocation will be done using mmap() it will still reserve virtual memory (can be problematic for a large number of fibers on 32 bit systems due to limited virtual memory addressing). The big advantage is that all kinds of internal function call (3 & 4) are supported without any changes to the existing codebase.
I agree with @bwoebi that a feature-complete implementation is more important than avoiding some "complexity". If stackless fibers were to support internal functions that would be a lot more complicated than the native implementation and require massive changes to a lot of PHP's source code. If internal calls are not supported it will limit the usability of fibers quite a bit because code using fibers might break depending on the calling context.
In conclusion: both solutions do have their downsides and are tricky to implement. It would be great if PHP could support stackless fibers for all use cases but i fear that it would require way too many changes to existing code making it more or less a PHP 8 thing. Maybe we could start with native fibers and switch to stackless fibers some time in the future when all internal calls can be inlined into the main VM loop. Changing the implementation should not be a problem because the PHP Fiber API used by scripts would not change.