I was wondering if anyone could answer me this quick question. I tried searching it but I get similar questions but in the wrong context.
What I am wondering is take this code:
function foo()
{
$test_array = array();
for($i=0; $i<10000000; $i++)
{
$test_array[] = $i;
}
}
What happens to $test_array after the function finishes. I know that it looses scope, I am not new to programming.
What I am wondering is should I call
unset($test_array);
before the function ends or does PHP set it for deletion to the garbage collector as the function ends?
I used the for loop just to show a variable of a fair size to get my point across.
Thanks for reading
Kevin
Once $test_array is no longer in scope (and there are no additional references that point to it), it is flagged for garbage collection.
It ceases to be in scope when the process returns from the function to the calling routine.
So there is no need to unset it.
This would only be different if you had declared $test_array as static.
unset() doesn't free the memory a variable uses, it just marks it for the garbage collector which will decide when to free the memory (when it has free cpu cycles or when it runs out of memory, whichever comes first).
However you have to realize that ALL memory used by a PHP script is freed when the script finishes which, most of the time, is measured in milliseconds, so if you're not doing any lengthy operations that would exceed the "normal" execution time of a PHP script you shouldn't worry about freeing memory.
Related
I have read several times that, in order to invoke the garbage collector and actually clean the RAM used by a variable, you have to assign a new value (e.g. NULL) instead of simply unset() it.
This code, however, shows that the memory allocated for the array $a is not cleaned after the NULL assignment.
function build_array()
{
for ($i=0;$i<10000;$i++){
$a[$i]=$i;
}
$i=null;
return $a;
}
echo '<p>'.memory_get_usage(true);
$a = build_array();
echo '<p>'.memory_get_usage(true);
$a = null;
echo '<p>'.memory_get_usage(true);
The output I get is:
262144
1835008
786432
So part of the memory is cleaned, but not all the memory. How can I completely clean the RAM?
You have no way to definitely clear a variable from the memory with PHP.
Its is up to PHP garbage collector to do that when it sees that it should.
Fortunately, PHP garbage collector may not be perfect but it is one of the best features of PHP. If you do things as per the PHP documentation there's no reasons to have problems.
If you have a realistic scenario where it may be a problem, post the scenario here or report it to PHP core team.
Other unset() is the best way to clear vars.
Point is that memory_get_usage(true) shows the memory allocated to your PHP process, not the amount actually in use. System could free unused part once it is required somewhere.
More details on memory_get_usage could be found there
If you run that with memory_get_usage(false), you will see that array was actually gc'd. example
There's a memory leak in my script and I couldn't find it after 2 days. I found the loop that is causing the memory leak; each iteration of the loop increases the memory usage. I moved the loop into a function to isolate the variables. At the end of the function, I unsetted every variable created by the function so that get_defined_vars() returns an empty array. Here's what I mean:
function the_loop(){
$var="value";
... // processing, including using a library
unset($var);
print_r(get_defined_vars()); // prints empty array
}
while(true){
the_loop();
echo memory_get_usage()."\n"; // steadily increases until memory limit is reached
}
I'm guessing that some variables defined in the_loop() are still in memory. I tried using XDebug's trace tool, but it didn't help. All it showed was that memory usage increases on average over the long run. I'm looking for a tool that can show me all the values in PHP's memory. I will be able to recognize the variable based on the value. What tool can dump PHP's memory?
As Dragon mentioned unset doesn't instantly free memory.
What's better at freeing memory with PHP: unset() or $var = null
I'd consider re-evaluating the way you're using PHP, it's not designed for long/constant running scripts, the garbage handler simply isn't that great.
If you want to dig further into the executing script I'd suggest checking out some tools like:
https://github.com/jokkedk/webgrind
http://xhprof.io/
http://derickrethans.nl/xdebug-and-tracing-memory-usage.html
Also worth a read: What gc_collect_cycles function is useful for?
Calling unset() does not force garbage collection, so while the reference count should decrease there may be others referencing it. Use xdebug_debug_zval($var) before calling unset to see how many references to its value there actually are.
So, I am running a long-running script that is dealing with memory sensitive data (large amounts of it). I (think) I am doing a good job of properly destroying large objects throughout the long running process, to save memory.
I have a log that continuously outputs current memory usage (using memory_get_usage()), and I do not notice rises and drops (significant ones) in memory usage. Which tells me I am probably doing the right thing with memory management.
However, if I log on to the server and run a top command, I notice that the apache process that is dealing with this script never deallocates memory (at least visibly though the top command). It simply remains at the highest memory usage, even if the current memory usage reported by php is much, much lower.
So, my question is: are my attempts to save memory futile if the memory isnt really being freed back to the server? Or am I missing something here.
Thank you.
ps. using php 5.4 on linux
pps. For those who want code, this is a basic representation:
function bigData()
{
$obj = new BigDataObj();
$obj->loadALotOfData();
$varA = $obj->getALotOfData();
//all done
$obj = NULL;
$varA = NULL;
unset($obj,$varA);
}
update: as hek2mgl recommended, I ran debug_zval_dump(), and the output, to me, seems correct.
function bigData()
{
$obj = new BigDataObj();
$obj->loadALotOfData();
//all done
$obj = NULL;
debug_zval_dump($obj);
unset($obj);
debug_zval_dump($obj);
}
Output:
NULL refcount(2)
NULL refcount(1)
PHP has a garbage collector. It will free memory for variable containers which reference count is set to 0, meaning that no userland reference exists anymore.
I guess there are still references to variables which you might think to have cleaned. Need to see your code to show you what is the problem.
I'm curious about using of unset() language construct just about everywhere, where I took memory or declare some variables (regardless of structure).
I mean, when somebody declares variable, when should it really be left for GC, or be unset()?
Example 1:
<?php
$buffer = array(/* over 1000 elements */);
// 1) some long code, that uses $buffer
// 2) some long code, that does not use $buffer
?>
Is there any chance, that $buffer might affect performance of point 2?
Am I really need (or should) to do unset($buffer) before entering point 2?
Example 2:
<?php
function someFunc(/* some args */){
$buffer = new VeryLargeObject();
// 1) some actions with $buffer methods and properties
// 2) some actions without usage of $buffer
return $something;
}
?>
Am I really need (or should) to do unset($buffer) within someFunc()s body before entering point 2?
Will GC free all allocated memory (references and objects included) within someFunc()s scope, when function will come to an end or will find return statement?
I'm interested in technical explaination, but code style suggestions are welcome too.
Thanks.
In php, all memory gets cleaned up after script is finished, and most of the time it's enough.
From php.net:
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.
In reality you would use unset() for cleaning memory pretty rare, and it's described good in this post:
https://stackoverflow.com/a/2617786/1870446
By doing an unset() on a variable, you mark the variable for being "garbage collected" so the memory isn't immediately available. The variable does not have the data anymore, but the stack remains at the larger size.
In PHP >= 5.3.0, you can call gc_collect_cycles() to force a GC pass. (after doing gc_enable() first).
But you must understand that PHP is script language, it's not Java so you shouldn't consider it like one. If your script is really that heavy to use tons of RAM - you can use unset and when script is close to exceed the memory - GC will trigger and clean up everything useless, including your unset variables. But in most cases you can forget about it.
Also, if you would want to go for unsetting every variable you do not use - don't. It will actually make your script execute longer - by using more CPU cycles - for the sake of getting free memory that would, in most cases, would never be needed.
Some people also say that they use unset to explicitly show that they won't use variable anymore. I find it a bad practice too, for me it just makes code more verbose with all these useless unsets.
I have two simple questions. What is better/useful for memory cleanup.
$var = null;
or
unset($var);
I have one function with one cycle. I am getting (after few minutes)
Fatal error: Allowed memory size of 419430400 bytes exhausted
I am setting null and unset()-ing every object (at the end of the cycle) but still without any success :( I cant find out what is consuming memory.
And what about function calls in cycle? Will PHP release all allocations in these functions?(after call)
PHP itself confuses both concepts sometimes but, in general, a variable set to NULL is not the same as a variable that does not exist:
<?php
$foo = 'One';
$bar = 'Two';
$foo = NULL;
unset($bar);
var_dump($foo); // NULL
var_dump($bar); // Notice: Undefined variable: bar
var_dump(get_defined_vars()); // Only foo shows up: ["foo"]=> NULL
?>
unset() does just that, it unsets a variable; but it does not immediate free up memory.
PHP's garbage collector will actually free up memory previously used by variables that are now unset, but only when it runs. This could be sooner, when CPU cycles aren't actively being used for other work, or before the script would otherwise run out of memory... whichever situation occurs first.
And be aware that unset won't necessarily release the memory used by a variable if you have other references to that variable. It will simply delete the reference, and reduce the reference count for the actual stored data by 1.
EDIT
While unset doesn't immediately release the memory used (only garbage collection actually does that) the memory that is no longer used as a result is available for the declaration of new variables
I found problem.
First it was caused by xdebug profilling tools (i have turned on everything :) ) - and it consume lot of memory.
So remember: xdebug (when profilling turned on) consumes some memory in PHP process of your application
Second, I didn't release static members used in called functions.
If you unset the variable it is just marked, so on the next garbage collection it will be removed. If setting to null, the data of the variable gets overwritten.
Maybe see also the comments on the php manual: Unset Manual
At least this behaviour is also what i have encountered so far.
But to fix it, you should first try to find out what is causing the memory to grow. The memory_get_usage function should be helpful for this.
And what about function calls in cycle? Will PHP release all allocations in these functions?(after call)
Once the execution leaves the scope of a function, all non-static variables are removed from memory.