Get variable refcount

php.internals

Martijn van Duren

9 years ago
Hello internals@, I'm new to this list, so let me first introduce myself. My name is Martijn van Duren and I work for a webhosting company in the Netherlands. Apart from that I'm also an OpenBSD h^Hslacker. tl;dr: How do I properly use Z_REFCOUNT on a zval? I'm faced with the following issue: I've build a framework which allows to talk to a remote interface over a persistent connection. This interface can return variables of arbitrary types. When an object is returned it is stored locally in an array accompanied by its id. This way I can ensure that the same object (and not an identical object) is returned on multiple requests. The problem I'm facing is that because this interface holds a reference of the object it's never truly released and thus a memory leak. For the application I use it for this is not an issue, but that might change in the future. To solve this I was thinking of creating a small extension which exports a function that gives me the active reference count. This way I could check in certain parts of the code if there's more than 1 variables linked to the object and if not, remove it from the internal array. This would not give a 100% result, but it's still better than hanging on to everything all the time. When playing with the extension I made the following function: PHP_FUNCTION(refcount) { zval var; zend_long refcount; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &var) == FAILURE) { return; } refcount = (zend_long) Z_REFCOUNT(var); RETURN_LONG(refcount); } Which didn't returned what I expected: $ php -r 'dl("refcount.so"); for ($a = 0; $a < 4; $a++) echo refcount($a)."\n";' 0 1 2 3 Could someone point me to what I'm doing wrong with Z_REFCOUNT? If there is a better way to solve my actual problem I would be all ears of course. Sincerely, Martijn van Duren

Nikita Popov

9 years ago
On Tue, May 30, 2017 at 9:11 AM, Martijn van Duren <php@list.imperialat.at> wrote:
> Hello internals@, > > I'm new to this list, so let me first introduce myself. > My name is Martijn van Duren and I work for a webhosting company in the > Netherlands. Apart from that I'm also an OpenBSD h^Hslacker. > > tl;dr: > How do I properly use Z_REFCOUNT on a zval? > > I'm faced with the following issue: > I've build a framework which allows to talk to a remote interface over > a persistent connection. This interface can return variables of > arbitrary types. When an object is returned it is stored locally in an > array accompanied by its id. This way I can ensure that the same object > (and not an identical object) is returned on multiple requests. > > The problem I'm facing is that because this interface holds a reference > of the object it's never truly released and thus a memory leak. For the > application I use it for this is not an issue, but that might change in > the future. > > To solve this I was thinking of creating a small extension which exports > a function that gives me the active reference count. This way I could > check in certain parts of the code if there's more than 1 variables > linked to the object and if not, remove it from the internal array. > This would not give a 100% result, but it's still better than hanging on > to everything all the time. > > When playing with the extension I made the following function: > PHP_FUNCTION(refcount) > { > zval var; > zend_long refcount; > > if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &var) == FAILURE) { > return; > } > > refcount = (zend_long) Z_REFCOUNT(var); > > RETURN_LONG(refcount); > } > > Which didn't returned what I expected: > $ php -r 'dl("refcount.so"); for ($a = 0; $a < 4; $a++) > echo refcount($a)."\n";' > 0 > 1 > 2 > 3 > > Could someone point me to what I'm doing wrong with Z_REFCOUNT? > If there is a better way to solve my actual problem I would be all ears > of course. > > Sincerely, > > Martijn van Duren >
Since PHP 7 not all zval types are refcounted. Before accessing Z_REFCOUNT you should first use Z_REFCOUNTED to check if a refcount exists. You are testing with integers, which is one of the not reference counted types. (Objects are always reference counted.) From your description, it sounds like you might be looking for the weakref PECL extension. Nikita

Martijn van Duren

9 years ago
On 05/30/17 10:23, Nikita Popov wrote:
> On Tue, May 30, 2017 at 9:11 AM, Martijn van Duren <php@list.imperialat.at> > wrote: > >> Hello internals@, >> >> I'm new to this list, so let me first introduce myself. >> My name is Martijn van Duren and I work for a webhosting company in the >> Netherlands. Apart from that I'm also an OpenBSD h^Hslacker. >> >> tl;dr: >> How do I properly use Z_REFCOUNT on a zval? >> >> I'm faced with the following issue: >> I've build a framework which allows to talk to a remote interface over >> a persistent connection. This interface can return variables of >> arbitrary types. When an object is returned it is stored locally in an >> array accompanied by its id. This way I can ensure that the same object >> (and not an identical object) is returned on multiple requests. >> >> The problem I'm facing is that because this interface holds a reference >> of the object it's never truly released and thus a memory leak. For the >> application I use it for this is not an issue, but that might change in >> the future. >> >> To solve this I was thinking of creating a small extension which exports >> a function that gives me the active reference count. This way I could >> check in certain parts of the code if there's more than 1 variables >> linked to the object and if not, remove it from the internal array. >> This would not give a 100% result, but it's still better than hanging on >> to everything all the time. >> >> When playing with the extension I made the following function: >> PHP_FUNCTION(refcount) >> { >> zval var; >> zend_long refcount; >> >> if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &var) == FAILURE) { >> return; >> } >> >> refcount = (zend_long) Z_REFCOUNT(var); >> >> RETURN_LONG(refcount); >> } >> >> Which didn't returned what I expected: >> $ php -r 'dl("refcount.so"); for ($a = 0; $a < 4; $a++) >> echo refcount($a)."\n";' >> 0 >> 1 >> 2 >> 3 >> >> Could someone point me to what I'm doing wrong with Z_REFCOUNT? >> If there is a better way to solve my actual problem I would be all ears >> of course. >> >> Sincerely, >> >> Martijn van Duren >> > > Since PHP 7 not all zval types are refcounted. Before accessing Z_REFCOUNT > you should first use Z_REFCOUNTED to check if a refcount exists. You are > testing with integers, which is one of the not reference counted types. > (Objects are always reference counted.)
Thanks for the explanation.
> > From your description, it sounds like you might be looking for the weakref > PECL extension.
That's even better than my original concept. Thanks.