Garbage collection:
referred to as GC. As the name suggests, it means reusing waste.
Before talking about the garbage collection mechanism, let’s first touch on memory leaks.
Recommended tutorial: "PHP7"
Memory leak:
An image explanation by a great god with a strong taste:
The general meaning is that if you apply for a piece of land and poop for a while, and then don't clean it up after pooping, then the land will be considered a waste. The more the land is used, the less it will be, and the final land will be full of poop. In the final analysis, remember to return it after use. To a certain extent, the garbage collection mechanism is used to wipe the butt.
C language garbage collection mechanism:
If you have used C language, the way to apply for memory is malloc or calloc. Then after you use up this memory, don’t forget it. Use the free function to release it. This is manual garbage collection. This method is usually used by masters.
What is the automatic garbage collection mechanism of php?
Let’s think about this problem first. We all know that php is implemented in C language. Think about how to use C language to implement statistics and release of a variable. How does C language implement a variable? From the time it is declared to the end when no one uses it, the memory occupied by the variable will be released (was garbage collected).
There are two core algorithms for PHP memory management:
One is reference counting, and the other is copy-on-write
When declaring a PHP variable, C The language generates a struct (structure) called zval at the bottom, as follows:
zval { string "a" //变量的名字是a value zend_value //变量的值,联合体 type string //变量是字符串类型 }
zval struct structure
(1) Save the variable name of php $a
(2) Variable type of php $a
(3) zend_value union of php variable $a
If a value is assigned to the variable, such as "hello world", then C language is at the bottom Generate a union (union) called zend_value
zend_value { string "hello world" //值的内容 refcount 1 //引用计数 }
zend_value union (union)
(1) Save the value of the variable of php $a hello world
(2) Record the number of references to the php $a variable
See the zval struct structure and zend_value. If the interviewer asks you why the php variable can save the string "123" and the number 123, do you know what to do? Did you answer it? The key point is that zval contains the type of the variable. When it is a string 123, the type is string, and the value points to "123"; when it is an integer 123, the type of zval is int and the value is 123.
What is reference counting?
Code actual analysis of php variable reference count
$a = 'hello,world'; echo xdebug_debug_zval( 'a');//refcount=1 $b = $a; echo xdebug_debug_zval( 'a'); //$b引用$a,故变量a,refcount=2 $c = $a; echo xdebug_debug_zval( 'a'); //$c引用$a,故变量a,refcount=3 unset( $c ); echo xdebug_debug_zval( 'a');//删除了$c的引用,故变量a,refcount=2
Running result:
a:
(refcount=1, is_ref=0)string 'hello, world' (length=11)
a:
(refcount=2, is_ref=0)string 'hello,world' (length=11)
a:
(refcount=3, is_ref= 0)string 'hello,world' (length=11)
a:
(refcount=2, is_ref=0)string 'hello,world' (length=11)
What is copy copying?
$a = 'hello'; $b = $a;//$a赋值给$b的时候,$a的值并没有真的复制了一份 echo xdebug_debug_zval( 'a');//$a的引用计数为2 $a = 'world';//当我们修改$a的值为123的时候,这个时候就不得已进行复制,避免$b的值和$a的一样 echo xdebug_debug_zval( 'a');///$a的引用计数为1
Run result:
a:
(refcount=2, is_ref=0)string 'hello' (length=5)
a:
(refcount=1, is_ref=0)string 'world' (length=5)
In fact, when you assign $a to $b, the value of $a does not I really made a copy. This is extremely disrespectful to the memory and time complexity. The computer just points $b to the value of $a. This is called fast and economical. So, when does replication actually occur? That is, when we modify the value of $a to 123, we have to copy it at this time to prevent the value of $b from being the same as $a.
Two key points are explained through simple cases: reference counting and copy-on-write.
Garbage collection mechanism:
When a zval is unset, or when it is run out of a function (that is, a local variable), etc., it will occur in many places. zval and zend_value are disconnected. At this time, what the zend engine needs to detect is whether the refcount of zend_value is 0. If it is 0, it will directly KO free the content. If the recount of zend_value is not 0, the value cannot be released, but it does not mean that the zend_value is innocent, because the zend_value may still be garbage.
(1) When the refcount of the php variable $a=0, the variable $a will be garbage collected
(2) When the refcount of the php variable $a>0, the variable $ aBut it may also be considered garbage
What kind of situation will cause the refcount of zend_value to be not 0, but this zend_value is garbage?
$arr = [ 1 ]; $arr[] = &$arr; unset( $arr );
这种情况下,zend_value不会能释放,但也不能放过它,不然一定会产生内存泄漏,所以这会儿zend_value会被扔到一个叫做垃圾回收堆中,然后zend引擎会依次对垃圾回收堆中的这些zend_value进行二次检测,检测是不是由于上述两种情况造成的refcount为1但是自身却确实没有人再用了,如果一旦确定是上述两种情况造成的,那么就会将zend_value彻底抹掉释放内存。
垃圾回收发生在什么时候?
有些同学可能有疑问,就是php不是运行一次就销毁了吗,我要gc有何用?并不是的,首先当一次fpm运行完毕后,最后一定还有gc的,这个销毁就是gc;其次是,内存都是即用即释放的,而不是攒着非得到最后,你想想一个典型的场景,你的控制器里的某个方法里用了一个函数,函数需要一个巨大的数组参数,然后函数还需要修改这个巨大的数组参数,你们应该是函数的运行范围里面修改这个数组,所以此时会发生写时拷贝了,当函数运行完毕后,就得赶紧释放掉这块儿内存以供给其他进程使用,而不是非得等到本地fpm request彻底完成后才销毁。
(1)fpm运行完毕后,最后一定会gc的
(2)运行过程中,也会gc的,内存都是即用即释放的,而不是攒着非得到最后gc
The above is the detailed content of Detailed explanation of PHP7 garbage collection mechanism (with complete flow chart of GC processing). For more information, please follow other related articles on the PHP Chinese website!