Haitao Lv · GitHub

Conversation

Haitao Lv added 2 commits

March 31, 2018 00:31

Haitao Lv

Haitao Lv

motecshine

zend_vm_stack_free_args(call);
zend_vm_stack_free_call_frame(call);

// TODO: cleanup

Haitao Lv

carusogabriel

Haitao Lv added 3 commits

March 31, 2018 18:16

Haitao Lv

Haitao Lv

Haitao Lv

tpunt

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;

Haitao Lv

@ghost

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.

taoso

{
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
if (EXPECTED(execute_data != NULL)) {
ZEND_INCR_VM_COUNT();

Read the original on github.com ↗