I have a snippet that resembles the following:
while (true) {
$myObject = new Class();
$myOtherObject = $myObject->getSomeOtherObj();
...
$myArray = [1, 2, 3];
...
sleep(1); //Sleep at the end, to save CPU.
}
This snippet should run as a daemon service, but I'm having a lot of trouble making this work.
The issue: each iteration increases the process memory usage. As if at each new iteration a new $myObject is being instantiated, but the previous one remains allocated in memory, and such.
I have tried:
to unset all variables at the end of the loop (right before the sleep()).
Setting all variables to null.
encapsulating them in a separate function (while (true) { doThis(); })
manually calling gc_collect_cycles()
None of those worked to decrease memory usage.
I have no idea how to force all memory to be released.
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).
I'm compiling my previous comments in an answer here. This doesn't explain exactly how you can free allocated memory, but it will guide you through a way to discover what in your application is causing that. With that, you can work on optimizing your code.
Finding memory usage bottlenecks is usually a challenging task. You can start by looking at your I/O-related calls, like database queries, file access, or even networking. Beyond increasing the execution time, sometimes these operations can allocate some amount of memory.
If you're already removing from memory the resources returned by I/O operations and no considerable decrease in allocated memory is noticed, the next step might be profiling your application using a tool like Blackfire (https://blackfire.io/).
Blackfire will give you a detailed view of each function call and its statistics on memory, CPU, and execution time. With that data, it's possible to check which operations are allocating excessive memory. You can find this info when you land your mouse pointer over the memory bar inside the call details, like this:
It is very likely (provided with the information given) that there are still references to the created object which prevent the garbage collector from removing the object from memory. Since it is basically counting references, therefor making sure that no reference is being stored, by either making copies of values or unsetting them carefully this can be avoided.
Normally it is easier when using while(true) constructs to not create objects precisely for this reason and make it as self contained as possible just to make sure that no memory leaks can actually happen.
I know this answer is not very helpfull in a direct manner (and I do not have enough rep to comment on the question) but it might get you on the right track.
The problem is that you are in an infinite loop, with no end at the request. The garbage collector of PHP is designed to be dealt with at the end of the request, and it not accessible to the user otherwise. PHP is designed to be called and discarded, not to be kept alive indefinately. Hence it is not fixable. So, what I would suggest is to create a chron job that restarts the php loop at regular intervals thus ending the request and freeing up the memory. See this document for details.
My best guess (due to lack of knowledge of the internals of the Classes involved) is that either the classes assign other Objects as their properties (or perhaps they have self-references) or that the array used (since the code sample resembles the real case) has a reference to itself, which would explain the memory leak if the size of the array is significant.
If it is of any help, please check out the reference counting fundamentals from php.net:
http://php.net/manual/en/features.gc.refcounting-basics.php
As both #m1lt0n and #MartPluijmaekers has mention above, this might be an issue related to object references.
We don't know what is inside your Class() class and getSomeOtherObj() method, so I can't say anything for sure, however below snippet might be able to help you figure out if that is the case or not.
/* Here is your Class */
class Class {
public function __construct () {
$this->child = new AnotherClass( $this );
}
/* This is what you have to have ... */
protected function __destruct () {
unset( $this->child );
}
}
/* Here is the other class */
class AnotherClass {
public function __construct ( $parent ) {
$this->parent = $parent;
}
}
/* Infinite Loop */
while ( true ) {
$myObject = new Class();
$myOtherObject = $myObject->getSomeOtherObj();
$myArray = [1, 2, 3];
/* manually destroying the object */
$myObject->__destruct();
unset( $myObject );
/* rest of free-ing goes here ... */
sleep(1); //Sleep at the end, to save CPU.
}
The snippet should be pretty much self-explanatory.
Related
This question already has an answer here:
How does pcntl_fork work in PHP?
(1 answer)
Closed 3 years ago.
I'm trying to run some code asynchronously within my class (see: https://github.com/duncan3dc/fork-helper). I need to call a series of methods that will modify the values of my properties. I can't seem to do so. I'm trying to use the last example of the call() method on this page: https://duncan3dc.github.io/fork-helper/usage/getting-started/
<?php
class foobar
{
private $x = 0;
public function doubler(&$number_to_double)
{
$number_to_double = $number_to_double * 2;
}
public function index()
{
$fork = new \duncan3dc\Forker\Fork;
$this->x = 5;
// outputs 5, as expected
var_dump($this->x);
$fork->call([$this, 'doubler'], $this->x);
$fork->wait();
// does not output 10, which is what I want
var_dump($this->x);
}
}
$my_foobar = new foobar();
$my_foobar->index();
I don't have to pass by reference, like I did in my doubler. Instead, I'm also open to just modifying the member from within the doubler method.
Why isn't my private member x doubling at the second var_dump()?
The linked library seems to be internally using pcntl_fork which performs a true fork of the running PHP process. The library mentions "threading" but this is not correct. Forking is a pretty low level operating system concept whereas a process creates a copy of its memory space and instructions in a new process. That new process becomes a child process of the forking process.
This means that everything, like included code and instantiated objects are copied and therefore a child process cannot directly modify the objects of the parent process. The only ways a child process can communicate with the parent is shared memory. In addition the parent can "wait" for the child process to terminate (failing to do this may result in zombie child processes). The linked library does not seem to implement true shared memory but (if you must) you could probably use the PHP shared memory library.
This however is impractical for simple tasks like the one you're sharing. In your case you need to use a true threading library like e.g. pthreads. Threads, unlike processes, are part of the parent process and share the same memory and data structures and have a significantly lower overhead when context switching.
Note: All the above concepts are pretty low level ones so maybe PHP is not the best choice of language to implement these.
I'm trying to debug a PHP memory leak. According to https://stackoverflow.com/a/29398380/2724978, PHP frees memory after function ends.. well, is that also valid for object functions?
My object has the following method:
function process All(){
$this->processA(); // intensive array processing - runs fine
$this->processB(); // intensive array processing - runs fine
$this->processC(); // intensive array processing - runs fine
$this->processD(); // intensive array processing - memory leak
}
Then I change to this:
function process All(){
$this->processD(); // intensive array processing - runs fine
}
So it appears that every function is piling up on the memory. Any ideas on how can I free it?
First, a clarification of terms (so that we're clear on what we mean when we say memory leak).
A memory leak is what happens when a program has allocated memory on the system that is no longer reachable by the program. This simply cannot happen as a direct result of your PHP code since PHP is solely responsible for managing your program's memory for you. Meaning that if a memory leak were to occur it would be a mistake made by PHP itself (the PHP memory manager) and not PHP code that you could have written. Only PHP extensions, which are written in C, and the PHP memory manager itself can leak memory. PHP code, cannot. I can assure you that the latter is exceedingly rare, if not impossible.
So according to this information, it is not possible for your PHP code to leak memory (period).
What you probably mean to say instead, is that you've either hit the user-defined PHP memory_limit or your code has a resulted in in OOM (Out of Memory) error. This is not what one would refer to as a memory leak, however. So it is crucially important that you include the actual OOM error along with your question in order to be able to decipher the problem with any degree of authority.
Because the answer you point to has to do with freeing local function variables, and the code you present as the problem, provides absolutely no indication that any local function variables are being used, it remains entirely unclear where memory is being allocated in the first place.
If I had to take a wild guess, I would say you're probably storing this array as an object property. Thus it remains in memory subject to any living reference of the object instance during that runtime.
The difference between a local variable and an instance property is that a local variable is destroyed after the function is finished. An instance property, however, is not destroyed until the object instance to which it belongs is destroyed. This doesn't happen until the last reference to that object is destroyed or you explicitly do so yourself.
class Foo {
protected $arr = [];
public function bar($baz) {
$this->arr[] = $baz; // object instance property
$quix = $baz; // local function variable
}
}
$foo = new Foo;
$foo->bar(1);
$foo->bar(2);
$foo->bar(3); // memory grows
In the above scenario the local variable $quix is always destroyed after each method call (this doesn't change whether you use a function or method, they are the same to PHP). However, the instance property $this->arr belongs to the object instance. So PHP cannot remove that from memory by itself until that instance $foo is destroyed or the script ends (implicitly destroys all memory).
I'm currently making a behavior that uses a plugin model internally.
Every time I need to look for a reference I use:
$this->Viewed = ClassRegistry::init('Viewed.Viewed');
So it will init the model that holds the data.
It's a good idea to use
$this->Viewed = ClassRegistry::removeObject('Viewed.Viewed')
to save memory in the excecution time of the script? or will add more time?
This behavior is used a lot in the code... so every gain is necesary.
Here's the code for CakePHP's ClassRegistry::removeObject($key) function:
public static function removeObject($key) {
$_this = ClassRegistry::getInstance();
$key = Inflector::underscore($key);
if (isset($_this->_objects[$key])) {
unset($_this->_objects[$key]);
}
}
Really all it's doing is unsetting the relevant key in an array the presumably holds all CakePHP's objects. The unset() function in PHP will not free up memory immediately, though PHP may reclaim that memory eventually. Since there's not much going on in ClassRegistry::removeObject() I wouldn't be too concerned with it taking up much more processing.
But keep in mind also that once a PHP script is finished being executed, memory will also be reclaimed. So there's not much point in calling ClassRegistry::removeObject() if you can only call it near the end of your script. PHP is not really designed for manual memory management like that. If memory really starts becoming an issue, you could also consider writing something external in another language that your application can call using exec().
Just a quick question about runtime...is it faster to run a script with many sequential commands or instantiate a new class object that calls each method to equal the same number of calls. Essentially what I'm asking is if writing "new Example();" and having it run through all of the methods is faster or slower than running through all the code in one sequential script. In my mind, I am imagining this in PHP.
<?php
echo new Example();
class Example
{
function __toString(){
$this -> method1();
$this -> method2();
$this -> method3();
$this -> method4();
}
function method1(){
//contents1;
}
function method2(){
//contents2;
}
function method3(){
//contents3;
}
function method4(){
//contents4;
}
}
?>
or
<?php
//contents1;
//contents2;
//contents3;
//contents4;
?>
Which one is faster or is it trivial and/or compiler dependent?
There will be added overhead when constructing a new object and calling the methods. But not much.
Other than that I don't think there would be much impact on speed, space however might very slightly because of the where PHP put things.
Objects are useful in OO design, scripts that are just meant to run once may as well be stand alone.
There are a bunch of other things like stack traces with objects as pet non-objects as well that might change if an error is encountered.
But to answer your question - minimal speed impact aside from the overhead of building / interpreting the object for php.
Further to this, read up on "time complexity" and "big oh" notation. The difference between sequential steps is trivial compared to how speed changes depending on your input 'n' and the complexity of your algorithm.
OOP will not affect the performance of your web application however there are several things that will, such as large amounts of data on the page, calling external web services and not setting time limits (RSS Feeds), large image files or lots of image files on a page, and hitting the database over and over again on post backs when it is not necessary. There are several other things which will hit the performance of your site but these are the basics.
There was a need to create a class object in the cycle. The cycle can be 1000 or more iterations. I'm having doubts about the use of memory. Therefore, the question of whether to do so?. Ready to hear the pros and cons of using this design. In advance thank everyone for answers.
Code example:
foreach($entities as $entity) {
$object = new $class($entity);
$object->doSomething();
}
Unless your class produce some trash in global space it won't affect (much) overall memory usage. Each instance will be disposed right at the end of cycle.
This wont affect memory. After each loop the new $object will fall out of scope and will be eligible for garbage collection. PHP is then free to remove the object from memory.