New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Non recursive cyclic garbage collector 7.3 #3923
Non recursive cyclic garbage collector 7.3 #3923
Conversation
… linked list stack
but without removing last element logic # Conflicts: # Zend/zend_gc.c
…cursive_cyclic_garbage_collector-7.3
…fore adding to stack
…cursive_cyclic_garbage_collector-7.3 # Conflicts: # Zend/zend_gc.c
tail call optimizations looks good, even if it makes the code a bit harder to maintain
…cursive_cyclic_garbage_collector-7.3 # Conflicts: # Zend/zend_gc.c
…ng will do nothing so we can avoid stack push pop
…cursive_cyclic_garbage_collector-7.3 # Conflicts: # Zend/zend_gc.c
…e that many changes on return types of the changed functions improved the stack altering functions so that we can migrate to a different type of stack with minimal changes
…cursive_cyclic_garbage_collector-7.3 # Conflicts: # Zend/zend_gc.c
… to allocate/free memory
…ne for every root scan there will be 4 maximum stacks created during a gc_collect_cycles run
…cursive_cyclic_garbage_collector-7.3 # Conflicts: # Zend/zend_gc.c
…cursive_cyclic_garbage_collector-7.3 # Conflicts: # Zend/zend_gc.c
…f color before processing it
…cursive_cyclic_garbage_collector-7.3 # Conflicts: # Zend/zend_gc.c
…rk_grey, gc_scan and gc_collect_white also stack_black used for gc_scan_black is defined on stack instead of heap gc_refcounted_stack_init will not create a stack but just initialize internal array gc_refcounted_stack_destroy will not destroy a stack but just destroy internal array
…cursive_cyclic_garbage_collector-7.3 # Conflicts: # Zend/zend_gc.c
…n the stack, it can be skipped useful for white scanning after marking when the item might have been marked as black in the meantime and also to reduce whitespaces changes
…cursive_cyclic_garbage_collector-7.3 # Conflicts: # Zend/zend_gc.c
return NULL; | ||
} else { | ||
(*stack) = (*stack)->prev; | ||
(*top) = GC_STACK_SEGMENT_SIZE - 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you can assign (*top) = GC_STACK_SEGMENT_SIZE
and remove return statement and inline else return block.
Following this you can inline the first else block as well as the if contained a return.
Apparently, code is easier to read without else
s.
: _stack->data[--_top]) | ||
gc_stack_pop(&_stack, &_top) | ||
|
||
static zend_never_inline gc_stack* gc_stack_next(gc_stack *stack) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this zend_never_inline
? It's used in only one place so it could have been manually inlined there so I imagine it could be inlined automatically also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used in only one place, but that place is an always-inline function. We want to inline the fast-path of stack pushing to each use, but we don't want to inline the rarely called reallocation code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right. It's not inlined on purpose, to reduce code size and improve register allocation on fast path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. For the future we might want to consider if we can't make get_gc directly write to the stack. The way get_gc currently works is very inconvenient because non-trivial cases require the object to allocate (and keep around forever) a separate gc buffer. If we could just push to the stack in get_gc things would be simpler.
tail_call: | ||
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) { | ||
ht = NULL; | ||
do { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason for the switch from tail_call to do-while in this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer to avoid "goto", if possible. I kept them in other places to minimize the patch.
Probably I'll re-factor the code in PHP-7.4 and master after merging this.
I agree about get_gc(), but this is for PHP-8 only, and probably, should be considered together with FE_FETCH improvements. |
Yes, definitely for PHP 8 only. What improvements for FE_FETCH do you have in mind? |
Avoid HashTable construction. |
Merged into PHP-7.3 and above. |
Thank you for helping with everything, I'm happy with it being merged. As with my previous benchmarks, I mentioned some performance improvements. I was wondering if we could measure the performance improvement for real applications and if anything changed there. |
In my benchmarks on PHP-Parser, the number of executed GC instructions (measured by callgrind) was reduced from 137M to 132.5M. So, 3% GC improvement in term of executed instructions, but this is not directly related to CPU cycles and time. |
No description provided.