Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP memory usage increase after unsetting arrays?

Tags:

php

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";
like image 989
JasonDavis Avatar asked Dec 07 '22 06:12

JasonDavis


1 Answers

I did a very quick test, after doing this :

  • declaring $iterations = 10; at the beginning of the script
  • using $p and not $i in the for loop (you are using $p to access array elements, and not $i)
  • adding a line to display used memory before the unsets

I am getting this, using PHP 5.3.1 (today's snapshot) :

328616
332176
331728

The three outputs are :

  • first one : the beginning of the script (the one which says "show current memory usage BEFORE")
  • second one : the one I added before the calls to unset ; just after the end of the for loop
  • third one : the one you put at the end of your script.

So, 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 ? *

like image 161
Pascal MARTIN Avatar answered Jan 05 '23 09:01

Pascal MARTIN