Good depth text: When writing copy and PHP garbage collection mechanism (rpm)

Original Address: http://www.php100.com/9/20/87255.html

Write copy (Copy-on-write, referred COW ) is an optimization strategy in the computer programming art. The core idea is that if there are multiple callers (callers) simultaneously require the same resources (such as data storage on memory or disk), they will get the same common pointers point to the same resource, until a caller tries to modify the resources when content, the system will really special copy of a copy (private copy) to the caller, while other callers have seen the original resource remains unchanged. This process to other callers are transparent (transparently). The main advantage of this approach is to share the same resources if a caller does not modify the resources, there will be a copy of the (private copy) is created, multiple callers just read operation.

In PHP COW

Note : The following code is based PHP5.6, after the reference counting mechanism PHP7 change.

As we all know, PHP is implemented by C, but C is a strongly typed language, PHP how to do a weakly typed language. Together look at, PHP variable code in C language bottom:

typedef struct _zval_struct the zval; 
typedef unsigned int zend_uint; 
typedef unsigned char zend_uchar; 
 
struct _zval_struct { 
 zvalue_value value; / * Note that this value is kept inside the variable * / 
 zend_uint refcount__gc; / * reference count * / 
 zend_uchar type; / * variable current data type * / 
 zend_uchar is_ref__gc; / * variables refer to the * / 
}; 
typedef Union _zvalue_value { 
 Long LVAL; / * PHP integer value * / 
 Double dVal; / * float PHP value * /
 struct { 
  char * Val;
  int len; 
 } STR; / * the PHP string * / 
 the HashTable * HT; / * array * / 
 zend_object_value obj; / * Object * / 
} zvalue_value;

PHP variables, is a low-rise structure zval, inside zvalue_value structure is actually a consortium, the consortium is to store the actual value of the variable PHP. Zend engine in order to distinguish the same zval address is shared by multiple variables, introduced ref_count and is_ref two variables are identified.

Run the following code, watch variables refcount changes:

<?php 
 $foo = 1; 
 xdebug_debug_zval('foo'); 
 $bar = $foo; 
 xdebug_debug_zval('foo'); 
 $bar = 2; 
 xdebug_debug_zval('foo'); 
?> 
//-----执行结果----- 
foo: (refcount=1, is_ref=0)=1 
foo: (refcount=2, is_ref=0)=1 
foo: (refcount=1, is_ref=0)=1

When the $ foo is assigned, only points to a value of $ foo $ foo variable by variable. When the value is assigned to $ foo $ bar, PHP and no memory copy to $ bar, but the $ foo and $ bar points to an address, and the reference count is incremented by one, which is the new 2 . Then, we changed the value of $ bar, then if the direct need the $ bar variables at the memory, the value is $ foo will also change. This is not the result we want. Thus, PHP kernel memory a copy out, and its value is updated assignment: 2 (this operation is also referred to as separating operation variable), while the variable points to the original $ foo $ foo only memory point, the reference count update It is: refcount = 1.

Let's look at an example to see memory, you can more easily see a clear role in the COW optimization of memory usage:

<?php 
$j = 1; 
var_dump(memory_get_usage()); 
$tipi = array_fill(0, 100000, 'php-internal'); 
var_dump(memory_get_usage()); 
$tipi_copy = $tipi; 
var_dump(memory_get_usage()); 
foreach($tipi_copy as $i){ 
 $j += count($i); 
} 
var_dump(memory_get_usage()); 
//-----执行结果----- 
$ php t.php 
int(630904) 
int(10479840) 
int(10479944) 
int(10480040)

The code above typical highlight the role of the COW, when the array variable $ tipi is assigned to $ tipi_copy, memory usage does not increase by half immediately, there is no significant change occurred in the number of looping through $ tipi_copy, here $ tipi_copy $ tipi variable data and common point to the same piece of memory, but not copied.

In other words, even if we do not use references, a variable is assigned, as long as we do not change the value of variables, will not apply for a new memory used to store data. Accordingly, we can easily think of some of the COW can be very effective to control memory usage scenarios: just use variables to calculate and rarely modify operations, such as the transfer function parameters, such as a large array of copy and so does not need to change the case of variable values.

Reference counting principle

Understanding of the internal storage structure php variable, and then understand the next php variable assignment related to the early principles and garbage collection.

PHP5.2 garbage collection algorithm used is the famous Reference Counting, Chinese translation of this algorithm is called "reference counting", the idea is very intuitive and simple: each memory object is assigned a counter, when a memory object is initialized to establish counter 1 (so at this time there is always a variable reference to this object), a new variable after each memory references this object, the counter is incremented each time the memory object to reduce a variable this references the counter by 1, when the garbage collection when the operation of the mechanism, all counters to 0 memory object destruction and recovery of its occupied memory.

Memory Leak

But there php5.3 previous version of garbage collection a loophole, that is, when the internal sub-element array or object reference to their parent, but this time if the situation delete parent element occurs, this variable container and will not be deleted, because its children are still pointing to the variable container, but since all are not symbolic scope of the variable container, it can not be removed, so the memory leak occurs, until the end of the script execution

If you already have Xdebug installed, you can call the function  xdebug_debug_zval () displays the value "refcount" and "is_ref" of.

For example:

Since the output poor example, Fig expressed as:

Good depth text: copy and garbage collection when written in PHP

For example:

unset($a);
xdebug_debug_zval('a');

Figure:

Good depth text: copy and garbage collection when written in PHP

Root buffering mechanism

php5.3 version introduced after the root buffering mechanism , i.e. php default settings specified number of root zval start buffer (default 10000), when there is found php zval circular references, which will put into the root buffer, when the root buffer reaches the number specified configuration file (default is 10000), the garbage will be recycled in order to resolve memory leaks caused by circular references

Why memory is not fully recovered to

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.

Garbage collection-related configuration

  • zend.enable_gc, the default value is on, if you want to turn off garbage collection mechanism can be set to off

Little knowledge

  • the unset () : the 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/wscsq789/p/11622255.html