dev*_*rCK 19 php php-internals
当我做基准测试时,我发现PHP 7使用的内存比PHP 5.6更多.
所以,我做了一个测试.我运行的脚本只包含:
$a=10;
Run Code Online (Sandbox Code Playgroud)
以下是我在没有任何模块的情况下使用PHP CLI时使用的内存的结果(php -n)
php 5.6 = 222600 Bytes
php 7.0 = 350448 Bytes
* PHP 5.6.23 (cli) (built: Jun 22 2016 12:13:15)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
* PHP 7.0.9 (cli) (built: Jul 20 2016 10:47:41) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
Run Code Online (Sandbox Code Playgroud)
环境是
谁能解释为什么我得到这个结果?
按照@gordon的建议使用此代码,
$i=0;
while ($i++ < 100000) ;
Run Code Online (Sandbox Code Playgroud)
php 5.6:227408字节
PHP 7.0:386640字节
我用这段代码确定了内存使用情况:
echo PHP_EOL;
echo "Memory Usage :".memory_get_usage();
echo PHP_EOL;
echo "Real Memory Usage :".memory_get_usage(true);
echo PHP_EOL;
echo "Real Peak Memory Usage :".memory_get_peak_usage(true);
echo PHP_EOL;
echo "Peak Memory Usage :".memory_get_peak_usage();
Run Code Online (Sandbox Code Playgroud)
Mob*_*Dev 22
要理解问题的答案 - 您需要了解PHP5和PHP7如何分配内存.
PHP5 通过它的Zend引擎结构来分配内存"按请求".
在PHP7这方面做了一些优化,所以内存分配"由块"
这种差异使得性能得到了非常好的提升(因为引擎不需要在每次运行时都在运行时分配内存并节省碎片时间),但它会增加"非常小"程序的内存消耗,这些程序的大小低于"块大小".
是的,PHP7在大型程序上非常节省内存.
您可以在下面的图片中查看所有这些差异:
使用基准构建的图形: 1.php
<?php
ini_set('memory_limit', '5G');
$a=range(1,$argv[1]);
echo PHP_EOL;
echo "Memory Usage :".memory_get_usage();
echo PHP_EOL;
echo "Real Memory Usage :".memory_get_usage(true);
echo PHP_EOL;
echo "Real Peak Memory Usage :".memory_get_peak_usage(true);
echo PHP_EOL;
echo "Peak Memory Usage :".memory_get_peak_usage();
echo PHP_EOL;
Run Code Online (Sandbox Code Playgroud)
bench.sh
// Small programs
(for i in $(seq 0 5 5000);do php5 dev/Tools/mem/1.php $i|cut -f 2 -d:|sed -r 's/^$/;/g'|sed -r 's/([0-9]+)$/\1,/g'|tr -d '\n'; echo $i; done)|tr -d '\n'|sed -r 's/$/]/g'|sed -r 's/^;/[/g'>php5.m
(for i in $(seq 0 5 5000);do php dev/Tools/mem/1.php $i|cut -f 2 -d:|sed -r 's/^$/;/g'|sed -r 's/([0-9]+)$/\1,/g'|tr -d '\n'; echo $i; done)|tr -d '\n'|sed -r 's/$/]/g'|sed -r 's/^;/[/g'>php7.m
//Large Programs
(for i in $(seq 0 50 100000);do php5 dev/Tools/mem/1.php $i|cut -f 2 -d:|sed -r 's/^$/;/g'|sed -r 's/([0-9]+)$/\1,/g'|tr -d '\n'; echo $i; done)|tr -d '\n'|sed -r 's/$/]/g'|sed -r 's/^;/[/g'>php5.m
(for i in $(seq 0 50 100000);do php dev/Tools/mem/1.php $i|cut -f 2 -d:|sed -r 's/^$/;/g'|sed -r 's/([0-9]+)$/\1,/g'|tr -d '\n'; echo $i; done)|tr -d '\n'|sed -r 's/$/]/g'|sed -r 's/^;/[/g'>php7.m
Run Code Online (Sandbox Code Playgroud)
八度抽屉
php7;php7=ans;
php5;php5=ans;
plot(php5(:,5)',[php5(:,1:4)';php7(:,1:4)']');
legend("PHP5 mgu", "PHP5 rmu", "PHP5 rpmu", "PHP5 pmu","PHP7 mgu", "PHP7 rmu", "PHP7 rpmu", "PHP7 pmu");
Run Code Online (Sandbox Code Playgroud)
Pao*_*olo 13
您的测试显示了PHP 7.0中更多的内存使用情况,因为测试代码非常简单.
由于内部ZEND引擎(解释器核心)的彻底重写,已知PHP 7.0使用的内存更少(并且更快)
正如Gordon评论的那样,很可能PHP 7.0中的新功能和改进需要一个"引导程序",当在小块代码上进行测试时会导致负面结果.
让我们尝试一些更复杂的东西:构建一个10.000整数的数组,然后使用Quicksort algorythm 对它进行排序.
这是我得到的结果:
PHP 7.0
Memory Usage: 1432752
Real Memory Usage: 4194304
Real Peak Memory Usage: 4194304
Peak Memory Usage: 3152360
PHP 5.6
Memory Usage: 2756744
Real Memory Usage: 4980736
Real Peak Memory Usage: 6029312
Peak Memory Usage: 5710464
Run Code Online (Sandbox Code Playgroud)
还有一个简单的20行快速排序远离现实世界的应用程序,有数千行代码,许多类声明,许多实例......
我在http://phptester.net上运行了测试
下面是代码
<?php
function quick_sort($array)
{
$length = count($array);
$pivot = $array[0];
$left = $right = array();
for($i = 1; $i < count($array); $i++)
{
if($array[$i] < $pivot)
{
$left[] = $array[$i];
}
else
{
$right[] = $array[$i];
}
}
return array_merge(quick_sort($left), array($pivot), quick_sort($right));
}
$unsorted = array();
for($i=0;$i<10000;$i++)
{
$unsorted[] = rand(1,1000000);
}
$sorted = quick_sort($unsorted);
$lf = "<br/>";
echo $lf;
echo "Memory Usage: ".memory_get_usage();
echo $lf;
echo "Real Memory Usage: ".memory_get_usage(true);
echo $lf;
echo "Real Peak Memory Usage: ".memory_get_peak_usage(true);
echo $lf;
echo "Peak Memory Usage: ".memory_get_peak_usage();
echo $lf;
Run Code Online (Sandbox Code Playgroud)
感谢PHP中的quicksort algorythm:http://andrewbaxter.net/quicksort.php
前期我想说,如果你在实际代码中看到PHP 7报告的内存使用量更高,最可能的原因是PHP 7会报告mysqlnd缓冲查询的内存使用情况,作为内存使用的一部分.在PHP 5中,未报告此内存使用情况(但当然仍使用内存).对于大型查询,这可以产生非常大的差异.
现在根据您的实际情况,这基本上是请求启动后立即使用PHP的内存使用情况.MobDev的答案已经解释了为什么"实际"内存使用存在差异,这是内存使用量指标,它报告PHP的分配器从内核的系统分配器请求了多少内存.正如MobDev所指出的那样,PHP 7将以更大的块(2MB)分配内存,并且对缓存已分配的块也更加积极.
但是,这并不能解释"非实际"内存使用中的差异,而这种内存使用并未将这些分配器详细信息考虑在内.通过使用内存分析器,例如通过运行PHP,很容易检查内存是否正常运行USE_ZEND_ALLOC=0 valgrind --tool=massif.该USE_ZEND_ALLOC=0部分指示PHP不使用自己的分配器.
首先,这将向您显示PHP报告的实际内存使用量和内存使用量差异非常大.Massif将为PHP 5.6显示3.2MB,对PHP 7显示2.3MB.原因是PHP仅报告通过其自己的分配器(ZMM)的内存,而许多在多个请求中存活的结构不使用它进行分配.
通过系统分配器的最大分配(因此未在内存使用中报告)是:
| PHP 5.6 | PHP 7
interned string buffer | 1 MB | 150 KB + strings
GC buffer | 320 KB | 320 KB
internal classes/funcs | >1.3 MB | >0.5 MB
Run Code Online (Sandbox Code Playgroud)
"内部类/功能"数字是粗略的下限,因为这里涉及许多小分配很难计算.一个主要区别是可见的,即PHP 7不使用固定的实习字符串缓冲区(列出的大小是我看到的哈希表缓冲区,它不包括字符串本身的大小).
但是,这仍然无法回答实际报告的内存使用情况的问题.在这种情况下,最大的分配是:
| PHP 5.6 | PHP 7
VM stack | 130 KB | 256 KB
Object store | 64 KB | (8 KB)
CG arena | --- | 64 KB
Run Code Online (Sandbox Code Playgroud)
这里有一些不同之处.主要的一点是PHP 7使用更大的VM页面大小(大约两倍大).此外,PHP 7使用竞技场来存储某些结构(如用户函数),它以默认大小64KB开始.另一方面,PHP 7中对象存储缓冲区的大小要小得多.
基本上TL; DR的答案是PHP 7使用更大的VM堆栈页面大小.