PHP Memory leakage and garbage collection

Source: Internet
Author: User

You have written a php script. Generally, you do not need to consider the memory leakage and garbage collection issues, because your script will soon be executed and exited.

However, when the program runs for a period of time and the data volume is large, the php script occupies too much memory and reports an error (PHP Fatal error: allowed memory size of 134217728 bytes exhausted) exited. In general, when the processing of each page ends, the new simple_html_dom object should be destroyed-but it does not actually exist. Obviously, memory leakage occurs.

Garbage collection mechanism of PHP

The garbage collection mechanism used before php 5.3 is a simple "reference count", that is, each memory object is allocated with a counter. When the memory object is referenced by a variable, the counter is + 1; when the variable reference is removed, counter-1; when counter = 0, indicates that the memory object is not used, the memory object is destroyed, and garbage collection is completed.

There is a problem with "reference count", that is, when two or more objects reference each other to form a ring, the counter of the memory object will not be reduced to 0; at this time, this group of memory objects is useless, but cannot be recycled, resulting in Memory leakage.

Php5.3 started with a new garbage collection mechanism. Based on reference counting, it implemented a complex algorithm to detect the existence of reference rings in memory objects to avoid Memory leakage.

Check for Memory leakage

Check whether the released memory is not released. You can simply call the memory_get_usage function to check the memory usage. The memory usage data returned by the memory_get_usage function is not very accurate, you can use the xdebug extension of php to obtain more accurate and detailed memory usage.

class A{    private $b;    function __construct(){        $this->b = new B($this);    }    function __destruct(){        //echo "A destruct\n";    }}class B{    private $a;    function __construct($a){        $this->a = $a;    }    function __destruct(){        //echo "B descturct\n";    }}for($i=0;;$i++){    $a = new A();    if($i00 == 0){        echo memory_get_usage()."\n";    }}

The preceding example creates a ring reference. Every time you create instance A of object a, a creates instance B of object B and allows B to reference. In this way, each A object is always referenced by a B, and each B object is referenced by an object A at the same time, so the reference ring is generated.

When executing this code in the php5.2 environment, we will find that the memory usage increases monotonically, and there is no "A/B desctruct" information output after the Destructor A and B are executed; until the memory is exhausted, the output is "PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 40 bytes )".

If you run this code in the php5.3 environment, you will find that the memory usage jumps up and down, but it never exceeds the limit. The program will also output A large number of "A/B desctruct", which indicates that the Destructor has been called.

This reference loop exists in my colleague's program, and his script is actually executed under php5.2.3. The simple_html_dom tool has two classes: simple_html_dom and simple_html_dom_node. The former contains a group member variable nodes, and each element in the array is a simple_html_dom_node object; each simple_html_dom_node object has a member variable dom. The dom value is the simple_html_dom object in front. This forms a beautiful reference ring, leading to memory leakage. The solution is also very simple, that is, when the simple_html_dom object is used up, it actively calls its clear function, clears its member variable nodes, the ring is broken, and the memory leakage will not happen.

Others

1. Garbage Collection Time

In PHP, if the reference count is 0, the memory is immediately released. That is to say, there is no variable referenced in the loop, and the memory is immediately released out of the scope of the variable. The ring reference detection is triggered when certain conditions are met. Therefore, in the above example, we can see that the memory usage fluctuates greatly. You can also use the gc_collect_cycles function to actively perform ring reference detection.

2. & Symbol impact

Explicitly referencing a variable increases the reference count of the memory:

$a = "something";$b = &$a;

At this time, unset ($ a), but there is still a reference of $ B pointing to the memory area, the memory will not be released.

3. Impact of unset Functions

Unset only disconnects a variable from A memory area, and calculates the reference count of the memory area-1. In the preceding example, inside the loop body, $ a = new (); unset ($ a); does not reduce the reference count of $ a to zero;

4. = effect of the null operation;

$ A = null: directly empty the data structure pointed to by $ a and return the reference count to 0.

5. Impact of script execution completion

After the script is executed, all memory used in the script will be released, regardless of whether there is a reference ring.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.