Test One:
class Entity { }
$entities = array();
echo "START: ". number_format(memory_get_usage()) . "\n";
for($i = 0; $i < 100000; ++$i)
{
$entities[] = new Entity();
}
echo "BEFORE UNSET: ". number_format(memory_get_usage()) . "\n";
unset($entities);
echo "AFTER UNSET: ". number_format(memory_get_usage()) . "\n";
Output:
START: 631,664
BEFORE UNSET:44,404,904
AFTER UNSET: 8,954,568
Test Two:
class Entity { }
$entities = array();
echo "START: ". number_format(memory_get_usage()) . "\n";
for($i = 0; $i < 100000; ++$i)
{
$entity = new Entity();
$entities[] = &$entity;
}
echo "BEFORE UNSET: ". number_format(memory_get_usage()) . "\n";
unset($entities);
echo "AFTER UNSET: ". number_format(memory_get_usage()) . "\n";
Output:
START: 631,664
BEFORE UNSET: 10,480,480
AFTER UNSET: 631,752
After i had trouble with memory limit, I played around with it a bit...
So after that i wonder how does garbage collection really work:
thx dave
So if you do what is here:
$entities = array();
echo "START: ". number_format(memory_get_usage()) . "\n";
for($i = 0; $i < 100000; ++$i)
{
$entities[] = new Entity;
}
echo "BEFORE UNSET: ". number_format(memory_get_usage()) . "\n";
foreach($entities as &$entity) {
unset($entity);
}
unset($entities);
echo "AFTER UNSET: ". number_format(memory_get_usage()) . "\n";
And you unset each object in the array. You get the same results as your second try:
Example:
START: 3,237,720
BEFORE UNSET: 21,297,640
AFTER UNSET: 3,237,488
Demo: http://codepad.org/oUjzA46D
Why does test one need more memory than test two?
PHP allocates more memory to store identifiers than it does for references (your first test assigns by identifier).
From the manual:
A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
This makes identifiers somewhat magical and they are specially handled.
Why does php keep memory after unsetting the array in test one?
unset
merely marks a variable's memory for freeing by the GC's algorithm; it doesn't free the memory right then. When I run your first test, a significant amount of memory is freed (although not as much as your second test, likely due to the greater sizes being allocated).
it is storing actual objects
is incorrect. Nor does your answer mention identifiers which are in no way actual objects
(try $entity = new Entity(); $entities[] = $entity;
). My answer also addresses his second question about why quite differently than yours - webbiedave 2012-04-05 18:59
those objects are still somewhat there
- webbiedave 2012-04-05 18:05