A concept,

The garbage collection mechanism is a dynamic storage allocation scheme. It automatically frees allocated memory blocks that the program no longer needs. Garbage collection allows programmers to focus less on program memory allocation and more on business logic.

In today’s popular languages, garbage collection is a common feature of the new generation of languages, such as Python, PHP, C#, Ruby, etc.

PHP garbage collection mechanism

Before PHP5.3, the garbage collection mechanism used was pure “reference counting”. (1) Each memory object is assigned a counter. When the memory object is referenced by a variable, the counter +1; ② When the variable reference is removed (after unset () is executed), the counter -1; ③ When the counter =0, it indicates that the memory object is not used, the memory object is destroyed, garbage collection is completed. PHP also frees up the contents of the process/thread at the end of a life cycle, so PHP doesn’t need to worry too much about memory leaks up front.

However, 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 point, the set of memory objects is no longer used, but cannot be reclaimed, resulting in a memory leak. Starting with php5.3, a new garbage collection mechanism, based on reference counting, implements a complex algorithm to detect the presence of reference rings in memory objects to avoid memory leaks.

2. With the development of PHP, the increase of PHP developers and the expansion of its business scope, a more complete garbage collection mechanism was introduced in PHP5.3. The new garbage collection mechanism solved the problem of reference memory leakage that could not handle the loop. As stated in the official documentation, each PHP variable is stored in a variable container called “zval”. A zval variable container that contains two bytes of additional information in addition to the type and value of the variable. The first is “is_ref”, which is a bool indicating whether the variable is a member of the reference set. This byte allows the PHP engine to distinguish normal variables from reference variables. Since PHP allows users to use custom references by using &, zval also has an internal reference counting mechanism to optimize memory usage.

The second extra byte is “refcount”, which indicates the number of variables (also known as symbols) pointing to the zval variable container. All symbols exist in a symbol table, where each symbol has a scope. Xdebug can be used to check reference counts:


      
$a = "new string";
$c = $b = $a;
xdebug_debug_zval( 'a' );
unset( $b.$c );
xdebug_debug_zval( 'a' );
? >
Copy the code

The above routine will print:

a: (refcount=3, is_ref=0) ='new string' 
a: (refcount=1, is_ref=0) ='new string'
Copy the code

Note: as of the NTS version of PHP7, references to the above routines will no longer be counted, i.e. C =c=c=b=$a after a’s reference count is 1. In PHP 7, zval can be reference-counted or unreferenced. There is a flag in the Zval structure that identifies this. Refcount will never count variables of type null, bool, int, and double. Refcount is the same as php5 for object and resource types. ③ For strings, unreferenced variables are called “actual strings”. Those referenced strings are double-deleted (that is, there is only one inserted string with specific content) and guaranteed to exist for the entire duration of the request, so reference counting is not required for them; If opCache is used, these strings will exist in shared memory, in which case you cannot use reference counting (because our reference counting mechanism is non-atomic); ④ For arrays, unreferenced variables are called immutable arrays. The array itself counts the same as IN PHP5, but each key-value pair in the array is counted as in the previous three rules (i.e., if it is a string, it is not counted). If opCache is used, the constant array literal in the code is converted to an immutable array.

Again, these live in shared memory and therefore cannot use refcounting. Here is our demo example:


      
echo 'Test string reference count';
$a = "new string";
$b = $a;
xdebug_debug_zval( 'a' );
unset( $b);
xdebug_debug_zval( 'a' );
$b = &$a;
xdebug_debug_zval( 'a' );
echo 'Test array reference count';
$c = array('a'.'b');
xdebug_debug_zval( 'c' );
$d = $c;
xdebug_debug_zval( 'c' );
$c[2] ='c';
xdebug_debug_zval( 'c' );
echo 'Test int count';
$e = 1;
xdebug_debug_zval( 'e' );
Copy the code

You see the following output:

Three, recycling cycle

By default, PHP garbage collection is turned on, and there is a php.ini setting that allows you to change it: zend.enable_gc.

When garbage collection is turned on, the algorithm determines that a circular lookup is performed whenever the root cache is full. The root cache has a fixed size, 10,000 by default, which can be changed by modifying the constant GC_ROOT_BUFFER_MAX_ENTRIES in the PHP source file Zend/zend_gc.c and then recompiling PHP. When garbage collection is turned off, the circular lookup algorithm never executes; however, the root will always exist in the root buffer, regardless of whether garbage collection is active in the configuration.

In addition to modifying the zend.enable_GC configuration, you can also turn garbage collection on and off when running PHP by calling the gc_enable() and gc_disable() functions, respectively. Calling these functions has the same effect as changing configuration items to turn the garbage collection mechanism on or off. Periodic collection can be enforced even when the root buffer may not be full. You can do this by calling gc_Collect_Cycles (). This function returns the number of cycles recovered using the algorithm.

The reason for allowing garbage collection to be turned on and off and for autonomous initialization is that some parts of your application may be time-sensitive. In this case, you may not want to use a garbage collection mechanism. Of course, turning off the garbage collection mechanism for parts of your application runs the risk of a possible memory leak, as some possible roots may not fit into the limited root buffer.

Therefore, it might be wise to call gc_Collect_Cycles () just before you call the gc_disable() function to free memory. Because this clears out all possible roots already in the root buffer, you can then leave an empty buffer for more space to store possible roots when the garbage collection mechanism is turned off.

Four, performance impact

1. Saving memory space

In the first place, the whole reason for implementing a garbage collection mechanism is to save memory footprint by cleaning up the variables referenced in the loop once the prerequisites are met. In PHP execution, garbage collection is performed whenever the root buffer is full or the gC_Collect_Cycles () function is called.

2. Increase the execution time

The second area where garbage collection affects performance is the time it frees up leaked memory consumption. In general, the garbage collection mechanism in PHP only has an increase in time consumption when the cyclic collection algorithm actually runs. But in normal (smaller) scripts there should be no performance impact at all.

3. The memory savings will allow more of these scripts to run on your server at the same time as normal scripts run with recycle mechanisms. Because the total memory usage did not reach the upper limit.

This benefit is particularly evident in long-running scripts, such as long-running test suites or daemon scripts. At the same time, the new garbage collection mechanism for scripted applications, which typically run longer than Web scripts, should significantly change the perception that memory leaks are difficult to solve.

The above content hopes to help you, more free PHP factory PDF, PHP advanced architecture video materials, PHP wonderful good article can be wechat search concerns: PHP open source community

2021 Jinsanyin four big factory interview real questions collection, must see!

Four years of PHP technical articles collation collection – PHP framework

A collection of four years’ worth of PHP technical articles – Microservices Architecture

Distributed Architecture is a four-year collection of PHP technical articles

Four years of PHP technical essays – High Concurrency scenarios

Four years of elite PHP technical article collation collection – database