Мне больше нравится потребление памяти в Php 7 по сравнению с PHP 5.6
Когда я делал бенчмарк, я обнаружил, что PHP 7 использует больше памяти, чем PHP 5.6.
Итак, я сделал тест. Я запустил script, содержащий только:
$a=10;
и ниже приведены результаты для памяти, используемой при использовании 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
Среда
- ОС: окно 10
- Сервер: IIS (хотя я использовал CLI, а не сервер), с быстрым cgi
- машина: 64 бит
- PHP-5.6.23-NTS-Win32-VC11-64
- PHP-7.0.9-NTS-Win32-VC14-64
Может кто-нибудь объяснить, почему я получил этот результат?
Дополнительные тесты
Используя этот код, как предлагается @gordon,
$i=0;
while ($i++ < 100000) ;
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();
Ответы
Ответ 1
Чтобы понять ответ на свой вопрос - вам нужно понять, как выделяет память PHP5 и PHP7.
PHP5
выделение памяти "по запросу", предполагая им структуру Zend Engine.
В PHP7
это некоторые оптимизации, сделанные с этой стороны, поэтому память выделяет "кусками"
- При запуске он выделяет большую часть памяти
- В распределении приложений он выделяет небольшой фрагмент, чтобы избежать фрагментации
Эти различия делают очень хорошее повышение производительности (из-за того, что движку не нужно выделять память во время выполнения каждый раз, когда вам это нужно, и экономить время на фрагментации), но это увеличивает потребление памяти для "очень маленьких" программ, размер которых ниже, чем "размер блока".
И да, PHP7 очень экономит память на больших программах.
Вы можете просмотреть все эти различия на рисунках ниже:
![Распределение памяти PHP для небольших программ]()
Графика, построенная с помощью эталона:
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;
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
октавный ящик
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");
Подробнее
Ответ 2
Ваши тесты показывают больше использования памяти в PHP 7.0, потому что код тестирования очень прост.
Известно, что PHP 7.0 использует меньше памяти (и быстрее), чем PHP 5.6 из-за радикальной перезаписи внутреннего ZEND Engine (ядро интерпретатора)
Как 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
И все же простая 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;
Кредит для алгоритма quicksort в PHP: http://andrewbaxter.net/quicksort.php
Ответ 3
Upfront Я хочу сказать, что если вы видите более высокий уровень использования памяти в PHP 7 на реальном коде, наиболее вероятной причиной является то, что PHP 7 будет сообщать использование памяти буферизованных запросов mysqlnd как часть использования памяти. В PHP 5 это использование памяти не сообщалось (но, разумеется, память все еще использовалась). Для больших запросов это может иметь очень существенную разницу.
Теперь к вашему фактическому случаю, который в основном относится к использованию памяти PHP сразу после запуска запроса. ответ MobDev уже объясняет, почему существует расхождение в "реальном" использовании памяти, которое является метрикой использования памяти, которая сообщает, сколько памяти PHP-распределитель запросил у системы распределитель ядра. Как указывает MobDev, PHP 7 будет выделять память на более крупные куски (2 МБ), а также более агрессивно относится к кэшированию выделенных блоков.
Однако это не объясняет расхождения в "нереальном" использовании памяти, что не учитывает данные распределителя. Легко проверить, идет ли речь о памяти, используя профилировщик памяти, например. запустив PHP через USE_ZEND_ALLOC=0 valgrind --tool=massif
. Часть USE_ZEND_ALLOC=0
указывает PHP не использовать собственный распределитель.
Прежде всего, это покажет вам, что фактическое использование памяти и использование памяти, описанное в PHP, значительно отличаются. Massif покажет использование 3.2MB для PHP 5.6 и 2.3MB для PHP 7. Причина в том, что 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
"Внутренние классы /funcs " - грубая нижняя граница, потому что здесь задействовано много небольших распределений, которые трудно подсчитать. Одно из основных различий видно, что PHP 7 не использует фиксированный интернированный строковый буфер (указанный размер является для буфера хэш-таблицы, который я вижу, который не включает размер самих строк).
Однако это все еще не отвечает на вопрос о фактическом использовании памяти. В этом случае наибольшие распределения:
| PHP 5.6 | PHP 7
VM stack | 130 KB | 256 KB
Object store | 64 KB | (8 KB)
CG arena | --- | 64 KB
Здесь есть пара различий. Главное, что PHP 7 использует больший размер страницы VM (примерно в два раза больше). Кроме того, PHP 7 использует арену для хранения определенных структур (например, пользовательских функций), которая начинается с размера по умолчанию 64 КБ. С другой стороны, размер буфера хранилища объектов значительно меньше в PHP 7.
Таким образом, ответ TL, DR заключается в том, что PHP 7 использует больший размер страницы стека VM.
Ответ 4
Php 5.6 требует меньше байтов по сравнению с Php 7.0.