Hi,
I'm hitting more and more the GC threshold in projects I work on (the "10k
roots" one), leading to high CPU usage. Usually, the GC finds nothing to
clean, so this is just a waste of CPU.
By being super light and fast, objects are nice for many tasks, and the
trend is to use them all over the place, e.g. as nodes when parsing a PHP
AST.
There is a way to work around: just call gc_disable()
. But this means
dealing with side effects of the engine in userland. Moreover, this also
means leaking memory, since meanwhile roots are not populated.
I was wondering: does it exist some light algorithm that could prevent
hitting the threshold that often?
E.g. in my previous example, AST nodes are created free of any circular
refs. Would it be possible to add them (and any objects really) to GC's
roots list only when userland does something that might create a
circular ref? (e.g. setting a property to a non scalar? or something more
clever?)
Just raising the topic, as unfortunately I wouldn't be able to do more.
Thanks for considering,
Nicolas
Hi,
There is a way to work around: just call
gc_disable()
. But this means
dealing with side effects of the engine in userland. Moreover, this also
means leaking memory, since meanwhile roots are not populated.
Maybe we could make gc_disable accept one reference zval as parameter, and
clear the GC_COLLECTABLE flag of zval.value->gc.u.v.flags. So, this zval
will never be put into gc root list.
On 26 Jul 2017, at 22:57, 吕海涛 0@lvht.net wrote:>> There is a way to work around: just call gc_disable()
. But this means
dealing with side effects of the engine in userland. Moreover, this also
means leaking memory, since meanwhile roots are not populated.
Maybe we could make gc_disable accept one reference zval as parameter, and
clear the GC_COLLECTABLE flag of zval.value->gc.u.v.flags. So, this zval
will never be put into gc root list.
I don't think it's a good idea to expose such an internal detail to userland. The more we expose, the more limits we will face in the future if we want to make some changes.
best regards,
CHU Zhaowei
Hi, internals,
I'm hitting more and more the GC threshold in projects I work on (the "10k
roots" one), leading to high CPU usage. Usually, the GC finds nothing to
clean, so this is just a waste of CPU.
More and more php frameworks use object/array as an global container to store
config, and these container variable will be used every where, but seldom
introduce the circular reference. Apart from this, these container variable
will always be a huge tree, so iterate them will lead to high CPU usage.
There is a way to work around: just call
gc_disable()
. But this means
dealing with side effects of the engine in userland. Moreover, this also
means leaking memory, since meanwhile roots are not populated.
In PHP-7.2, the GC_COLLECTABLE flag has been moved into the gc struct, and
this make it possible to prevent gc trace for certain zval.
So I propose to make the gc_disable function accept one zval reference as
parameter. And if gc_disable get that zval, gc_disable just drop the zval’s
GC_COLLECTABLE flag, which will hint the PHP gc not to trace that zval.
Here is my patch https://github.com/php/php-src/pull/2665/files, and a demo,
<?php
function hi($a)
{
return $a->name;
}
$a = new stdclass;
$a->name = 'foo';
gc_disable($a);
hi($a); // these will change the refcount of $a, but never trace gc
Hi,
So I propose to make the gc_disable function accept one zval reference as
parameter. And if gc_disable get that zval, gc_disable just drop the zval’s
GC_COLLECTABLE flag, which will hint the PHP gc not to trace that zval.
i dont know if this is a good idea or not. But for the "s" in solid,
create a new function like gc_exclude to exclude variables from the
garbage collector and do not add a parameter to gc_disable.
Hi,
So I propose to make the gc_disable function accept one zval reference as
parameter. And if gc_disable get that zval, gc_disable just drop the zval’s
GC_COLLECTABLE flag, which will hint the PHP gc not to trace that zval.i dont know if this is a good idea or not. But for the "s" in solid, create a new function like gc_exclude to exclude variables from the garbage collector and do not add a parameter to gc_disable.
A new function gc_hint($zval, bool $collectable) has been introduced at