Talking about the garbage collection mechanism PHP--

Foreword

Most programming language will have its own garbage collection mechanism, php is no exception. Often heard many people say that gc, that is, the garbage collector, the entire process for Garbage Collection.

Before php5.3, it does not include garbage collection, and no special garbage collector, garbage collection is achieved simply determine what variables zval the refcount is 0, then it is released.

But if such a simple judgment garbage collection, it is easy to cause memory overflow during the program. If the situation "itself to itself" exists, then the variable will not be recycled back into memory leaks, so php5.3 from the beginning there have been dedicated to cleaning up garbage data to prevent memory leaks garbage collector.

 

Reference counting basics

We have to understand GC, then we must first understand what causes garbage collection base Yes.

In php, each variable exists called "zval" variable container. A zval container, comprising in addition to the type and value of the variable, further comprising two additional bytes of additional information. The first is "is_ref". The second is the "refcount".

is_ref is a Boolean value, the variable used to indicate whether the set of reference. Through this byte, the ordinary php to engine variables and references to distinguish, due php allows users to "&" is used in reference to the custom, therefore there zval an internal reference counting mechanism to optimize memory.

refcount The number of variables used to represent a zval container. All symbols exist among a symbol table, each symbol has a scope.

Popular talk:

1, refcount is the number of variables is the same with the same value, then this value is refcount

2, is_ref is when there are variables in the form of a & assignment, then the value will increase is_ref

<?php$a = "new string"; ?>

In the above code, the variable is a current generated in the action, and generating a variable of type String and the container is "new string" a. This is the default setting when is_ref become false, because now there is no reference to generate customized. refcount been set to 1. We can use php to see the changes in these counts, first of all need to use xdebug, so php is not installed on the need to extend the xdebug first installed it.

<?php

$a = "new string"; xdebug_debug_zval('a');

输出:a: (refcount=1, is_ref=0)='new string'

?>

Increasing the reference count zval

<?php

$a = "new string";

$b = $a;

xdebug_debug_zval( 'a' );  输出:a: (refcount=2, is_ref=0)='new string'

?>

 

In this case reference number is 2 because container is the same variable associated with a b variables and variables. When not necessary, php not to replicate the generated container is variable. Variable container when the "refcount" becomes zero is destroyed when any variable associated with a variable container leaves its scope: the time (such as function execution end), or variable function call unset (), "refcount "will be minus one.

Reducing the reference count

<?php

$a = "new string";

$c = $b = $a;

xdebug_debug_zval( 'a' );

unset( $b, $c );

xdebug_debug_zval( 'a' ); 

输出: a: (refcount=3, is_ref=0)='new string' a: (refcount=1, is_ref=0)='new string'

?>

 

Performing  the unset ($ A); , and the value of the type comprising a container of this variable will be removed from memory.

Composite type

When the type of the variable array or object such as a complex type, array and object types of variables to their own members or property exists in the symbol table.

<?php

$a = array( 'meaning' => 'life', 'number' => 42 );

xdebug_debug_zval( 'a' ); 

输出: a: (refcount=1, is_ref=0)=array (    'meaning' => (refcount=1, is_ref=0)='life',    'number' => (refcount=1, is_ref=0)=42 )

?>

The above code, we can understand, look for the array as a whole, for the value of the internal point of view is an independent entity, each have a zval the refcount and is_ref. The picture below is picking down from the official website:

Add elements to an existing array:

 

<?php

$a = array( 'meaning' => 'life', 'number' => 42 );

$a['life'] = $a['meaning']; xdebug_debug_zval( 'a' );

输出: a: (refcount=1, is_ref=0)=array (    'meaning' => (refcount=2, is_ref=0)='life',    'number' => (refcount=1, is_ref=0)=42,    'life' => (refcount=2, is_ref=0)='life' )

?>

 

FIG explained as follows:

Remove an element from the array:

<?php

$a = array( 'meaning' => 'life', 'number' => 42 );

$a['life'] = $a['meaning'];unset( $a['meaning'], $a['number'] );

xdebug_debug_zval( 'a' );

输出: a: (refcount=1, is_ref=0)=array (    'life' => (refcount=1, is_ref=0)='life' ) ?>

 

Remove the array element, which is similar in effect to delete from a variable array after deletion reduce the value of refcount where this element of the container, when refcount is zero, the variable container is deleted from memory. 

Adding to the array itself as an element:

 

<?php

$a = array( 'one' );

$a[] =& $a; xdebug_debug_zval( 'a' );

输出: a: (refcount=2, is_ref=1)=array (    0 => (refcount=1, is_ref=0)='one',    1 => (refcount=2, is_ref=1)=... )

?>

 

We can also see that the array a second element of the array, the variable pointing to the container refcount is 2, "..." indicating the occurrence of the output of the above recursive operations, it means "..." points to the original array .

Although there is no longer any sign of a scope pointing to this structure (that is, variable container), due to the array element "1" still points to the array itself, so this can not be cleaned. Because there is no other sign pointing to it, the user no way to clear this structure, the result will lead to memory leaks.

 

Garbage collection cycle

In versions prior to 5.3, php can not handle referenced memory leaks cycle. However, since the 5.3 php synchronization algorithm using reference counting system synchronization cycle recovered, this process only memory leak.

The basic idea is to increase a reference count if it will continue to be used, of course, is no longer a waste. If the reference count is decremented to zero, where the variable container will be cleared. So in other words only when the reference count is reduced to a non-zero value, it will produce garbage cycle. In a garbage reference period by checking whether the count is decremented by 1, and checks the number of containers which reference variable is zero, which is to find garbage.

 

We took this picture, for example (from the php official website). In order to avoid having to examine all possible reference counting garbage reduction cycle synchronization algorithm on all possible root root buffer (root buffer) in (marked with purple in FIG referred suspected spam), which ensures at the same time each possible garbage root appears only once in the buffer. Only when the root buffer is full, all the different variables fishes container garbage collection operation performed in the buffer, as reflected in step A. FIG.

In step B, purple remove each analog variable. Probably will not purple different variable reference number minus 1, if a common variable reference count becomes zero, it is common for this variable is doing a mock Delete to delete the simulation. Each variable can only be deleted once the simulation, the simulation delete marked in gray.

In step C, the recovery of each analog variable purple. Of course, this recovery is conditional, when the variable reference count is greater than 0 when its done to restore the simulation. Also each variable can only be restored once the recovery is marked as black, so birth to not be able to recover is the deletion of the blue node, traversal step out in the real D deleted.

In the php garbage collection is enabled by default in your php.ini can be set manually, it is turned on or off by the garbage collection mechanism zend.enable_gc this property. When turned on the garbage collection mechanism, whenever the root buffer is full, it will perform the cycle described above search algorithm. Root buffer has a fixed size, of course, you can Zend / zend_gc.c in constant GC_ROOT_BUFFER_MAX_ENTRIES to modify the size of the root buffer area (after the note changes need to be recompiled php) by modifying php source file. When closed garbage collection mechanism, this cycle will not be executed search algorithm, however, possible roots will always exist in the root buffer, regardless of the configuration is active garbage collection.

Of course, you can also open and close the garbage collection calls gc_enable () and gc_disable () function, the same effect and modify configuration items. Even root buffer is not yet full, but also to enforce the recovery cycle.

 

php memory management mechanism

Now we already know how the story zval. So now we need to know php memory management mechanism of how it is.

 

var_dump(memory_get_usage());

$ Test = "This is a test ah";

var_dump(memory_get_usage());

unset($name);

var_dump(memory_get_usage());

Output (php5.6): /var/www/html/node_test/phptest/phptest.php:51: int (361896) /var/www/html/node_test/phptest/phptest.php:53: int (361928) / var / www / html / node_test / phptest / phptest.php: 55: int (361896)

 

Process: define variables -> memory increase -> Clear Variable -> Memory recovery

 

var_dump(memory_get_usage());

$ Test = "This is a test ah";

var_dump(memory_get_usage());

unset($name);

var_dump(memory_get_usage());

Output (php7.1): /var/www/html/node_test/phptest/phptest.php:51: int (361896) /var/www/html/node_test/phptest/phptest.php:53: int (361928) / var / www / html / node_test / phptest / phptest.php: 55: int (361928)

 

And I found that when using php7 this problem, which would be different php5 and said memory management and garbage collection php7 of, here for the time being is not the table. We continue to go down.

When execution

$ Test = "This is a test ah";

Memory allocation does two things:

  1. Allocate memory for the variable name, and stored in the symbol table
  2. Allocate memory for the variable value

We look at the code:

 

var_dump(memory_get_usage());

for($i=0;$i<100;$i++) {

     $a = "test".$i;     $$a = "hello";    

}

var_dump(memory_get_usage());

for($i=0;$i<100;$i++) { 

    $a = "test".$i;      unset($$a);    

}

var_dump(memory_get_usage());

Output: /var/www/html/node_test/phptest/phptest.php:57: int (363520) /var/www/html/node_test/phptest/phptest.php:63: int (372384) / var / www / html /node_test/phptest/phptest.php:69: int (369216)

 

Why memory is not fully recovered come from?

Since the core structure Hashtable PHP, defined impossible when enough time allocation of memory blocks, the initialization of only a small distribution, and the like is not enough time during the expansion, the expansion is not only reduced Hashtable, so when 100 variables into the symbol table is not enough time spent on expansion once, when unset () just put the memory value assigned to a variable, but the memory allocated for the variable name or symbol table, the symbol table and not shrink, so confiscation of memory is occupied back to the symbol table.

php is not enough memory on the whereabouts of long time OS for memory, but to apply for a chunk of memory, and then distributed to the part of applicants, so then there is need to apply logical memory, you do not need to apply again the memory of the OS, avoid duplication of applications, only when a chunk of memory is not enough to go apply. And when freeing memory, php not put the memory back to the OS, but to maintain its own memory track list of free memory for reuse.

The new version of php (after version 5.3) is the memory of how to deal with garbage?

Above we have just talked about, for garbage in the ring php quoted lead, resulting in a new synchronization algorithm (GC algorithm), the official website for the theory, I had to understand:

If a refcount zval the increase, it indicates that variable zval still in use, is not spam

If a zval of refcount reduced to 0, then zval can be freed, can clear, not garbage

If, after deleting a simulation of zval refcount minus 1, if the number of citations zval is greater than zero, then zval can not be released, possibly a garbage

 

Little knowledge about garbage collection

unset (): unset () simply disconnects a connection to a variable memory area, the memory area while the reference count is decremented by 1, memory is recovered mainly to see whether the refcount to 0.

null: The null is directly assigned to a variable data structure pointed to the variable blanking, while its reference count to go to zero.

End of script execution: the script all memory will be released, regardless of whether there is a reference ring.

Guess you like

Origin www.cnblogs.com/FLy-1992/p/11645875.html