Recycling may have a slight performance impact, but this is only when comparing PHP 5.2 to PHP 5.3. Although in PHP 5.2, logging may be slower than not logging at all, other changes to the PHP run-time in PHP 5.3 reduce this performance penalty.
There are two main areas that have an impact on performance. The first is the saving of memory space, and the other is the increase in execution time (run-time delay) when the garbage collection mechanism performs memory cleaning. We will look at both areas.
Memory Footprint Savings
First of all, the whole reason for implementing a garbage collection mechanism is to save memory footprint by cleaning up circularly referenced variables once the prerequisites are met. In PHP execution, garbage collection is performed once the root buffer is full or the gc_collect_cycles() function is called. In the figure below, the memory usage of the following scripts in PHP 5.2 and PHP 5.3 environments is shown, excluding the basic memory occupied by PHP itself when the script is started.
Example #1 Memory usage example
<?php class Foo { public $var = '3.1415962654'; } $baseMemory = memory_get_usage(); for ( $i = 0; $i <= 100000; $i++ ) { $a = new Foo; $a->self = $a; if ( $i % 500 === 0 ) { echo sprintf( '%8d: ', $i ), memory_get_usage() - $baseMemory, "\n"; } } ?>
In this very theoretical example, we create an object and a property in this object is set to point back to the object itself. A typical memory leak occurs when the variables in the script are copied again during the next iteration of the loop. In this example, two variable containers are leaked (the object container and the attribute container), but only one possible root can be found: the variable that was unset. After 10,000 repetitions (resulting in a total of 10,000 possible roots), when the root buffer is full, a garbage collection mechanism is performed and the memory associated with the possible roots is released. This is easily seen in the sawtooth memory usage graph of PHP 5.3. After each execution of 10,000 repetitions, garbage collection is performed and related reused reference variables are released. Since the leaked data structure is very simple in this example, the garbage collection mechanism itself doesn't have to do much work. From this chart, you can see that the maximum memory footprint of PHP 5.3 is about 9 Mb, while the memory footprint of PHP 5.2 keeps increasing.
Run-Time Slowdowns
The second area where garbage collection affects performance is the time it takes to release leaked memory. To see how long this takes, we slightly changed the above script to have more repetitions and remove the memory usage calculation in the loop. The second script code is as follows:
Example #2 GC performance influences
<?php class Foo { public $var = '3.1415962654'; } for ( $i = 0; $i <= 1000000; $i++ ) { $a = new Foo; $a->self = $a; } echo memory_get_peak_usage(), "\n"; ?>
We will run this script twice, once when garbage collection is turned on by configuring zend.enable_gc and once when it is turned off.
Example #3 Running the above script
time php -dzend.enable_gc=0 -dmemory_limit=-1 -n example2.php # and time php -dzend.enable_gc=1 -dmemory_limit=-1 -n example2.php
On my machine, the first command lasted about 10.7 seconds, while the second command took 11.4 seconds. Time increased by 7%. However, the peak memory usage when executing this script was reduced by 98%, from 931Mb to 10Mb. This benchmark is not very scientific or representative of real application data, but it does show the benefits of garbage collection in terms of memory footprint. The good news is that for this script, when more circular reference variables appear in the execution, the memory savings are greater, and the percentage increase in time is 7% each time.
PHP internal GC statistics
Inside PHP, you can display more information about how the garbage collection mechanism operates. But to display this information, you need to recompile PHP first to make the benchmark and data-collecting code available. You need to set the environment variable CFLAGS to -DGC_BENCH=1 before running ./configure as you wish. The following command string does just that:
Example #4 Recompiling PHP to enable GC benchmarking
export CFLAGS=-DGC_BENCH=1 ./config.nice make clean make
When you re-execute the above example code with the newly compiled PHP binary file, after the PHP execution ends, you will see The following information:
Example #5 GC statistics
GC Statistics ------------- Runs: 110 Collected: 2072204 Root buffer length: 0 Root buffer peak: 10000 Possible Remove from Marked Root Buffered buffer grey -------- -------- ----------- ------ ZVAL 7175487 1491291 1241690 3611871 ZOBJ 28506264 1527980 677581 1025731
The main information statistics are in the first block. You can see that the garbage collection mechanism ran 110 times, and in these 110 runs, a total of more than 2 million memory allocations were released. As long as the garbage collection mechanism runs at least once, the root buffer peak (Root buffer peak) is always 10000.
Conclusion
Usually, the garbage collection mechanism in PHP only consumes time when the loop collection algorithm does run. Increase. But in normal (smaller) scripts there should be no performance impact at all.
However, in the case of normal scripts with recycling mechanisms running, the memory savings will allow more such scripts to run on your server at the same time. Because the total memory used has not reached the upper limit.
This benefit is especially obvious in long-running scripts, such as long-running test suites or daemon scripts. At the same time, for PHP-GTK applications that typically run longer than web scripts, the new garbage collection mechanism should greatly change the long-held view that memory leaks are difficult to solve.