Circular References
Circular-references has been a long outstanding issue with PHP. They are caused by the fact that PHP uses a reference counted memory allocation mechanism for its internal variables. This causes problems for longer running scripts (such as an Application Server or the eZ Components test-suite) as the memory is not freed until the end of the request. But not everybody is aware on what exactly the problem is, so here is a small introduction to circular references in PHP.
In PHP a refcount value is kept for every variable container (zval). Those containers are pointed to from a function's symbol table that contains the names of all the variables in the function's scope. Every variable, array element or object property that points to a zval will increase its refcount by one. The refcount of a zval container is decreased by one whenever call unset() on a variable name that points to it, or when a variable goes away because the function in which it was used ends. For a more thorough explanation about references, please see the article on this that I wrote for php|architect some time ago.
The problems with circular references all start by creating an array or an object:
<?php $tree = array( 'one' ); ?>
This creates the following structure in memory:
Now if we proceed to add a new element to the array, that points back to the array with:
<?php $tree[] = $tree; ?>
We create a circular reference like this:
As you can see there are two variable names pointing to the array itself. Once through the $tree variable, and once through the 2nd element of the array. Because there are two variable names pointing to the container, its refcount is 2.
Now, the next step that actually creates the problem if we unset() the $tree variable. As I mentioned before an unset() on a variable name will decrease the refcount of the variable container the variable points to, in this case the array value. The structure in memory now looks like this:
Note that there is no variable pointing to the array container anymore. Because of this PHP has no way of freeing this data anymore, and the memory leak is born. PHP however does remove all allocated variables at the end of each request, so it's not a hard-memory leak, but it's still annoying enough for long running scripts and daemons written in PHP.
Luckily there are a few solutions to this problem. The first one is to use a new garbage collection algorithm, another is to augment the reference counting system with some cyclic tracing . The latter solution is something that is currently undertaken by David Wang, one of the Google Summer of Code students. He mentioned he is making good progress and I can hardly wait until I can play with it :)
Comments
With MDB2, I ran into a situation where I needed circular references. MDB2 can be extended with modules. These module instances need to be attached to the mdb2 instance so that they can be used like so: $mdb2->manager->listTables();
The manager property stores the instance of the manager module.
Now obviously inside the manager module we need to be able to execute a query, which in turn requires that the manager module have a reference to the MDB2 instance. Bad, ugly etc.
So my solution is still not pretty, though I guess it could get cleaned up a bit by making more use of OO constructs. So what I do is that I actually store a reference to all MDB2 instances into a global array. In the constructor of all modules I do not pass in the MDB2 instance but instead I pass the key to the global array that points to the MDB2 instance. Of course this global array is cleaned up via a destructor.
Lukas: maybe you shoud make some kind of singleton, which would store references to those objects? I think Symfony does it this way (sfContext class)
also, you can add some kind of destructor to singleton, which would effectively deinitialize it, on user request…
Derick: yup. I am impatiently waiting to see the result of Davids work too.
But my other thought is, that in most cases one can easily solve problems without circular references, and in most cases they are the sign of bad design
Actually I am already leveraging this global array to provide a "singleton". I put that in quotes, because you might obviously require access to multiple different database at the same time. However for the purposes I described, its a lot more performat and reliable to use the approach I described instead of going through the normal singlaton end user API I also provide.
Great to hear that.. I'm tired of manually calling __destruct() methods :)
Life Line
@beasts Is your ns1 doing OK? I am getting warning from monitoring that it is timing out and having different results than ns2.
Updated a restaurant
I walked 8.5km in 1h50m50s
I consider myself a decent photographer, but then you find out about the likes of Angel Fux (https://www.angelfux.com/portfolio), and I would like to crawl into a hole.
Better alignment from multiple GPS tracks for QE II Garden (and removed duplicated node)
After two busy days doing elections stuff, I spent yesterday looking at birds, in a nature reserve to relax and recharge.
I saw some cracking birds, with these being my favourite shots.
#BirdPhotography #photography #BirdsOfMastodon #Nature #London
I walked 8.0km in 1h26m01s
Updated a restaurant
Updated 3 bird_hides; Confirmed 2 informations and a toilet
I walked 7.0km in 3h10m47s
This map was mostly red yesterday.
I'm glad we managed to win all the wards we've targeted.
However, no overall control, and two parties with the same amount of seats in second place.
I walked 2.2km in 41m46s
I walked 1.9km in 19m17s
I've spend most of my time outside polling telling today, taking down poll card numbers so we don't need to chase people up to go vote.
I have made several observations:
Updated a restaurant
I walked 12.1km in 2h3m04s
I walked 1.1km in 9m46s
I walked 1.2km in 10m31s
Updated a waste_basket
Created 11 benches, 2 life_rings, and 3 other objects; Updated 8 benches and a waste_basket; Deleted a bench and a log; Confirmed a cafe
I walked 7.8km in 1h52m27s
Tomorrow we have elections in the UK!
Lots of local authorities, all London Councils, the Welsh Senedd, and the Scottish Parliament.
Don't forget to vote if you have the right.
I get to vote for myself again 😎.
Benches, and corrections for the QE II Gardens
Addresses on College Road
Created 2 main entrances and an entrance; Updated an entrance, a residential building, and a house building



Shortlink
This article has a short URL available: https://drck.me/cr-5li