aRomanyuk
@aRomanyuk
Архитектор, психолог, писатель

PHP. Почему увеличивается пиковое значение используемой памяти при очистке переменных и массивов?

Я проводил оптимизацию производительности в своих PHP скриптах.
Вижу, что по ходу исполнения скрипта много не нужных данных в памяти.
Возникла идея очистить данные, полученные из БД, когда ими попользовался, с помощью unset-ов.
Чем раньше сотру, тем быстрее они не будут занимать память - логика такая.

К примеру:
$a=mysql_query("SELECT etc");
 while($b=mysql_fetch_assoc($a)){
     //do some
}
unset($a);


Я вводил всё новые unset-ы.

Оказалось, то при каждом новом unset($a) у меня уменьшается значение, выдаваемое memory_get_usage() (не сюрприз), но при этом растёт значение пикового потребления памяти скриптом, выдаваемое memory_get_peak_usage()

Вот таким замерщиком я получал данные о потребляемой памяти
$log->LogDebug('MemUsage (after all) '.(memory_get_usage()-$base_memory_usage).'. Memory peak was '.memory_get_peak_usage(TRUE).'.');

И в логе вижу с каждой итерацией после введения нового unset в код (не за один запуск!):
MemUsage (after all) 281080. Memory peak was 559024.
MemUsage (after all) 275008. Memory peak was 576728.
MemUsage (after all) 274608. Memory peak was 579024.
MemUsage (after all) 274272. Memory peak was 786432.


Не очень понятно, почему при удалении массивов и переменных пиковое использование памяти скриптом растёт. Я ожидал, что оба значения будут уменьшаться, так как считал, что пиковое значение memory_get_peak_usage(TRUE) - это максимальное значение memory_get_usage()

И вот не знаю, делаю я лучше или хуже?
  • Вопрос задан
  • 153 просмотра
Пригласить эксперта
Ответы на вопрос 1
SerafimArts
@SerafimArts
Senior Notepad Reader
Не очень понятно, почему при удалении массивов и переменных пиковое использование памяти скриптом растёт.


Потому что unset не удаляет ничего, а добавляет в zval новые данные - флаг удаления, для того, чтобы GC смог подчистить их при следующем запуске (Хотя это тоже не так, GC в пыхе почти ничего не подчищает, а просто перезаписывает поверх, т.к. аллокации памяти требуют времени).

А сама операция unset нужна лишь для того, чтобы корректно убирать данные в реалтайм (т.е. грубо говоря while true) приложениях, если нет уверенности в том, что refcount после отработки кода у zval будет равен 0. Если же в приложении нет никакого эвентлупа, то использование unset и gc_collect_cycles будет лишь добавлять тормозов и пиков потребления памяти.

Это не абсолютная истина, конечно. Но лучше доверить менеджмент памяти именно PHP. Но например, в приведённом выше коде, который устарел лет на 10 и сейчас просто не будет работать - после последней строчки не останется вообще никаких переменных в памяти. Точнее они останутся, но с refcount = 0, а значит создание новой переменной просто перезапишет уже выделенную память.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы