Reputation: 48933
I run the code below without unsetting the arrays and then with unsetting the arrays using PHP's
unset($array-here)
And the memory number increases when I use the unset. Any ideas why? ANd better yet, what is the proper way to free memory?
NOTICE: PLEASE, no preaching about pre-optimizing, its EVIL and all that, this is a test so don't lecture about it please and thank you.
//show current memory usage BEFORE
echo memory_get_usage() . "\n"; // 57960
//start timer
$start3 = microtime(true);
// arrays for header menu selector
$header_home = array('home' => true);
$header_users = array('users.online' => true, 'users.location' => true, 'users.featured' => true, 'users.new' => true, 'users.browse' => true, 'users.search' => true, 'users.staff' => true);
$header_forum = array('forum' => true);
$header_more = array('widgets' => true, 'news' => true, 'promote' => true, 'development' => true, 'bookmarks' => true, 'about' => true);
$header_money = array('account.money' => true, 'account.store' => true, 'account.lottery' => true, 'users.top.money' => true);
$header_account = array('account' => true);
$header_mail = array('mail.inbox' => true, 'mail.sentbox' => true, 'mail.trash' => true, 'bulletins.post' => true, 'bulletins.my' => true, 'bulletins' => true);
//run throught 1,000 iterations
for($i = 0; $i < $iterations; ++$i) {
if(isset($header_home[$p]))
$current_home = 'current';
else if(isset($header_users[$p]))
$current_users = 'current';
else if(isset($header_forum[$p]))
$current_forum = 'current';
else if(isset($header_more[$p]))
$current_more = 'current';
else if(isset($header_money[$p]))
$current_money = 'current';
else if(isset($header_account[$p]))
$current_account = 'current';
else if(isset($header_mail[$p]))
$current_mail = 'current';
}
//unset the arrays
unset($header_money);
unset($current_home);
unset($current_users);
unset($current_forum);
unset($current_more);
unset($current_account);
unset($current_mail);
//show time
$end3 = microtime(true);
echo number_format($end3 - $start3, 7) . ' Time3 ARRAY<br />';
//show current memory usage AFTER
echo memory_get_usage() . "\n";
Upvotes: 4
Views: 10706
Reputation: 3553
I don't know if that makes any difference, but you didn't unset $start3
, $end3
and every other $home_xxx
array than $home_money
.
Also i would suggest keeping the benchmark more simple. Like only using one array for instance.
Keep it simple. It will make your test/benchmark more meaningful.
EDIT:
Just played around with it a bit..
First Test
<?php
$array = array();
echo "START:". memory_get_usage() . "\n";
for ( $i = 0; $i<1000; $i++ ) {
$array[] = 'foo';
}
echo "BEFORE UNSET: " . memory_get_usage() . "\n";
unset($array);
echo "AFTER UNSET: " . memory_get_usage() . "\n";
sleep(120);
echo "AFTER A WHILE: " . memory_get_usage() . "\n";
Output:
START:53632
BEFORE UNSET: 146360
AFTER UNSET: 118848
AFTER A WHILE: 118848
Second test:
<?php
$array = array();
echo "START:". memory_get_usage() . "\n";
for ( $i = 0; $i<1000; $i++ ) {
$array[] = 'foo';
}
echo "BEFORE UNSET: " . memory_get_usage() . "\n";
for ( $i = 0; $i<count($array); $i++ ) {
unset($array[$i]);
}
unset($array);
echo "AFTER UNSET: " . memory_get_usage() . "\n";
Output:
START:53944
BEFORE UNSET: 146680
AFTER UNSET: 119128
So the theory that unset only schedules for garbage collection doesn't hold(at least not in PHP 5.2.8, but then again they changed a lot in the GC of PHP 5.3).
I'm afraid there's not much more that you can do than unset :-(
Upvotes: 1
Reputation: 105878
unset()
is not a "force garbage collection" mechanism.
So calling unset()
doesn't mean the memory that variable was holding is instantly available, it just means that variable is scheduled for garbage collection. The PHP engine does that on its own schedule.
Upvotes: 1
Reputation: 401002
I did a very quick test, after doing this :
$iterations = 10;
at the beginning of the script$p
and not $i
in the for loop (you are using $p
to access array elements, and not $i
)I am getting this, using PHP 5.3.1 (today's snapshot) :
328616
332176
331728
The three outputs are :
for
loopSo, the unsets do actually provoke the liberation of some memory, and not the increase of memory used ;-)
But only a pretty small portion of the allocated memory is freed...
Now, the question might be "what is causing some memory to be used and not freed, event if I call unset on the arrays" -- actually, it is probably what you first meant ?
Well, I suppose unsetting the arrays themselves doesn't force PHP to free the memory allocated for items inside the arrays...
Like this note on the unset manual page says (quoting) :
unset() does just what it's name says - unset a variable. It does not force immediate memory freeing. PHP's garbage collector will do it when it see fits - by intention as soon, as those CPU cycles aren't needed anyway, or as late as before the script would run out of memory, whatever occurs first.
If you are doing $whatever = null; then you are rewriting variable's data. You might get memory freed / shrunk faster, but it may steal CPU cycles from the code that truly needs them sooner, resulting in a longer overall execution time.
And, actually, this might look interesting ;-)
Still, doing a couple of quick tests doesn't get anything quite interesting ; I suppose my script / data is not big enough to force PHP to free unused memory, or something like this...
Note : if I use gc_collect_cycles
(PHP >= 5.3) to force a garbage collection after the unsets, it doesn't change a thing -- I suppose it's because there is no "lost cycle".
*BTW : running your code gave me quite a couple notices (the $p vs $i, for instance) ; do you develop with error_reporting set to report notices ? *
Upvotes: 10
Reputation: 3906
You're first call to memory_get_usage()
is before arrays exist. You should do it between the creations + filling of your arrays and your unset()
's
Here what you see is just that more memory is used at the end of the script than at the beginning.
Upvotes: 3