Every computer language has its own automatic garbage collection mechanism, so that programmers don’t have to worry too much about program memory allocation. PHP is no exception. However, in object-oriented programming (OOP) programming, some objects need to be displayed. Destruction in a certain way to prevent program execution memory from overflowing.
1. PHP garbage collection mechanism (Garbage Collector (GC)
In PHP, when no variable points to this object, the object becomes garbage. PHP will destroy it in memory; this is PHP's GC garbage disposal mechanism to prevent memory overflow. When a PHP thread ends, all memory space currently occupied will be destroyed, and all objects in the current program will be destroyed at the same time. The GC process generally starts running with each SESSION. The purpose of gc is to automatically destroy and delete session files after they expire.
2. __destruct /unset
__destruct() destructor is executed when the garbage object is recycled. Unset destroys the variable pointing to the object, not the object.
3. Session and GC
Due to the working mechanism of PHP, it does not have a daemon thread to regularly scan Session information and determine whether it is invalid. When a valid request occurs, PHP will based on the values of the global variables session.gc_probability and session.gc_divisor, To decide whether to enable a GC, by default, session.gc_probability=1, session.gc_divisor =100 means there is a 1% possibility of starting a GC (that is, only one gc in 100 requests will be accompanied by 100 started by a request).
The job of GC is to scan all Session information, subtract the last modification time of the session from the current time, and compare it with the session.gc_maxlifetime parameter. If the survival time exceeds gc_maxlifetime (default 24 minutes), the session will be deleted. However, if your web server has multiple sites, GC may have unexpected results when processing sessions at multiple sites. The reason is that when GC is working, it does not distinguish between sessions of different sites.
So how to solve it at this time?
Look at the example below:
Example 1: gc.php
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; echo $b ."n"; ?>
Needless to say, the output of % php -f gc.php is very clear:
hy0kl% php -f gc.php I am test.
Okay, next one:
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; $b = 'I will change?'; echo $a ."n"; echo $b ."n"; ?>
The execution results are still obvious:
hy0kl% php -f gc.php I will change? I will change?
Please take a look:
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; unset($a); echo $a ."n"; echo $b ."n"; ?>
Do you have to think about it?
hy0kl% php -f gc.php Notice: Undefined variable: a in /usr/local/www/apache22/data/test/gc.php on line 8 I am test.
Look again:
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; unset($b); echo $a ."n"; echo $b ."n"; ?>
In fact, if you understand Example 3, this one is similar to it.
hy0kl% php -f gc.php I am test. Notice: Undefined variable: b in /usr/local/www/apache22/data/test/gc.php on line 9
Look:
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; $a = null; echo '$a = '. $a ."n"; echo '$b = '. $b ."n"; ?>
What’s the first feeling of violence?
hy0kl% php -f gc.php $a = $b =
Yes, this is the output result. PHPers who already have a deep understanding of PHP GC will not find it strange. To be honest, I was surprised when I ran this code for the first time, but it made me have a deep understanding of PHP GC. A deeper understanding. Then the following examples of co-workers are naturally easy to understand.
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; $b = null; echo '$a = '. $a ."n"; echo '$b = '. $b ."n"; ?>
Let’s analyze GC and references in detail:
In all examples, a variable is created. In simple terms, this process is to open up a space in the memory and store a string I am test in it. . There is a symbol table inside PHP to record the reference count of each block of memory. At this time, the reference count of this block of memory will be increased by 1, and a label (variable) named $a will be used to point to this block of memory, which is convenient for labeling. name to operate the memory.
Perform & operation on variable $a. My understanding is to find the memory pointed by $a, establish the same reference point for $b, and store the string I am test. The reference count of the memory block in the symbol table is increased by 1. In other words, when our script reaches this line, the string I am test is stored. The piece of memory is referenced twice. What should be emphasized here is that the & operation establishes a reference pointer, not a pointer. PHP has no concept of pointers! At the same time, some people have proposed a file soft link similar to UNIX. It can be understood to a certain extent: storing the character I am test. The piece of memory is a real file of ours, and the variables $a and $b are soft links established for the real file, but they point to the same real file. So, we see that when $b is assigned a value in Example 2, the value of $a also changes. It is similar to operating a file through a soft link.
在 Example 3 与 4 中,进行了 unset() 操作。根据实际的执行结果,可以看出: unset() 只是断开这个变量对它原先指向的内存的引用,使变量本身成为没有定义过空引用,所在调用时发出了 Notice ,并且使那块内存在符号表中引用计数 减 1,并没有影响到其他指向这块内存的变量。换言之,只有当一块内存在符号表中的引用计数为 0 时, PHP 引擎才会将这块内存回收。
看看下面的代码与其结果:
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; unset($a); unset($a); unset($a); echo '$a = '. $a ."n"; echo '$b = '. $b ."n"; ?>
输出:
hy0kl% php -f gc.php Notice: Undefined variable: a in /usr/local/www/apache22/data/test/gc.php on line 10 $a = $b = I am test.
第一次 unset() 的操作已经断开了指向,所以后继的操作不会对符号表的任何内存的引用记数造成影响了。
赋值 null操作是相当猛的,它会直接将变量所指向的内存在符号号中的引用计数置 0,那这块内存自然被引擎回收了,至于何时被再次利用不得而知,有可能马上被用作存储别的信息,也许再也没有使用过。但是无论如何,原来所有指向那块内存变量都将无法再操作被回收的内存了,任何试图调用它的变量都将返回 null。
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; $b = null; echo '$a = '. $a ."n"; echo '$b = '. $b ."n"; if (null === $a) { echo '$a is null.'; } else { echo 'The type of $a is unknown.'; } ?>
输出:
hy0kl% php -f gc.php $a = $b = $a is null.
综上所述,充分说明了为什么我们在看开源产品源码的时候,常看到一些比较大的临时变量,或使用完不再调用的重用信息都会被集中或显示的赋值为 null 了。它相当于 UNIX 中直接将真实文件干掉了,所有指向它的软链接自然成了空链了。
之前在讨论到这些细节点时有很多想当然的念头,在实际的执行了测试代码后才发现: 哦,原来如此!纸上得来终觉浅,绝知此事须躬行。