Force Freeing Memory in PHP

What's better at freeing memory with PHP: unset() or $var = null

It was mentioned in the unset manual's page in 2009:

unset() does just what its 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.

(Since 2013, that unset man page don't include that section anymore)

Note that until php5.3, if you have two objects in circular reference, such as in a parent-child relationship, calling unset() on the parent object will not free the memory used for the parent reference in the child object. (Nor will the memory be freed when the parent object is garbage-collected.) (bug 33595)


The question "difference between unset and = null" details some differences:


unset($a) also removes $a from the symbol table; for example:

$a = str_repeat('hello world ', 100);
unset($a);
var_dump($a);

Outputs:

Notice: Undefined variable: a in xxx
NULL

But when $a = null is used:

$a = str_repeat('hello world ', 100);
$a = null;
var_dump($a);

Outputs:

NULL

It seems that $a = null is a bit faster than its unset() counterpart: updating a symbol table entry appears to be faster than removing it.



  • when you try to use a non-existent (unset) variable, an error will be triggered and the value for the variable expression will be null. (Because, what else should PHP do? Every expression needs to result in some value.)
  • A variable with null assigned to it is still a perfectly normal variable though.

PHP free memory after unset

PHP has garbage collector which takes care of the memory management for you, which affects to memory usage (of the process) in several different ways.

First, when inspecting memory usage of a process outside of the process, even if PHP sees some memory to be freed, it may not be released back to the OS for optimization purposes related to memory allocation. This is reduce overhead from continuous frees and allocs, that happen more easily with GC’d languages, as allocation procedure is not visible to the actual program.

For that reason, even if one calls gc_collect_cycles() by hand, the memory may not be freed to the OS at all, but rather reused for future allocations. This causes PHP to see smaller memory usage than the process in reality uses, due to some early big reservation which never gets to freed back to the OS.

Second, due to nature of garbage collection, the memory may not be immediately freed after marked unused by the program. Calling gc_collect_cycles() will make the memory freed immediately, but it should be seen unnecessary, and does not work if you have logical (or something in PHP leaks) memory leak in your script.

For knowing what is going on, doing line by line inspection (for example with Xdebug’s function trace) would give you better insight about how PHP (or rather, your program) sees the memory usage.

Combining that to line-by-line inspection from outside of the process (for example your pmap commands) would tell if the PHP actually is freeing any memory at any point after reserving it.

How to force PHP to release memory after script is finished

When script is completed all resources should be freed, so you should not be in need of doing anything extra unless you use PHP/lib that seems to be buggy and leaks memory

EDIT

Memory leak is result of a bug and in languages like PHP if memory leak happens in PHP or its modules you will not be usually able to fix it other way by updating PHP or used modules to never version and hope this will come with leak fixed. You may try to narrow down what component is leaking and then report to its authors. As temporary solution you can work this issue around by restarting your httpd periodically which shall free all memory allocated by php or modules. But that's quick workaround only

PHP: Having some memory issues inside a loop

After much research on the topic, I am finally convinced that there are no ways to manually force the memory to be released or to force object destruction.

However, something that has helped me lower the memory usage (absolutely preventing infinite memory stacking was not possible) was to realize that there are no loop scopes in PHP and that the Garbage Collection happens when switching scopes.

In C# or Java, a variable created within a while (...) {} is only accessible from within the loop. This is not the norm for PHP. A $myObject created from within a while instruction is accessible throughout your entire application.

This means the provided snippet would be better presented as:

while (true) {
myFunc();
}

function myFunc()
{
$myObject = new Class();
$myOtherObject = $myObject->getSomeOtherObj();
...
$myArray = [1, 2, 3];
...
sleep(1); //Sleep at the end, to save CPU.
}

Encapsulating the logic in a function forces the scope to change, which means the Garbage Collector will be called at each iteration. This has not solved my problem, but it has lowered my RAM usage somewhat.

What I have learned from this experience is that PHP is probably not suited to this specific project requirement. I'd need more control over memory, and PHP doesn't provide any kind of control over created/destroyed objects. Some native functions do not release memory properly (specially those that do I/O, database access and memcached).

Way to free memory in recursive functions?

Recursive functions will always suck up memory. Each call will use up a bit more until you reach the bottom and start returning. This is unavoidable. Doing unset() on the function's parameters won't help you... they've already taken up space on the call stack and can't be removed until the function returns.

One option would be to switch over to an iterative function, but that's harder to do with a tree-structure.

But most of all, what does this function actually accomplish? You're returning arrays, but not assigning them anywhere in the calling level, so you're creating a ton of arrays only to throw them away again immediately.

Unset ing class to clear memory

This can happen if any other object keeps reference to either $twitterObj itself or some big data inside it. You could define a destructor __destruct() for the class to see if the object is actually destroyed (it is called on actual destruction).

I would also recommend using a profiler - such as xhprof or xdebug or Zend products - to see memory usage and find where the memory is wasted.



Related Topics



Leave a reply



Submit