Don't add simple objects to GC's roots

  100048
July 26, 2017 14:57 nicolas.grekas@gmail.com (Nicolas Grekas)
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
  100060
July 27, 2017 13:00 0@lvht.net (=?utf-8?B?5ZCV5rW35rab?=)
Hi,
> On 26 Jul 2017, at 22:57, Nicolas Grekas grekas@gmail.com> 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.
  100064
July 27, 2017 16:14 me@jhdxr.com ("=?gb18030?B?va26/rTzz7rIyg==?=")
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
  100118
July 30, 2017 03:44 i@lvht.net (Haitao Lv)
Hi, internals,

> On 26 Jul 2017, at 22:57, Nicolas Grekas grekas@gmail.com> wrote: > > 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, name; } $a = new stdclass; $a->name = 'foo'; gc_disable($a); hi($a); // these will change the refcount of $a, but never trace gc
  100120
July 30, 2017 10:19 gmblar@gmail.com (Andreas Treichel)
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.
  100482
September 9, 2017 06:59 i@lvht.net (Haitao Lv)
> On 30 Jul 2017, at 18:19, Andreas Treichel <gmblar@gmail.com> wrote: > > 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 https://github.com/php/php-src/pull/2665/files