Язык
Контакты
GitHub
Поддержка
Регистрация
Войти
Логин: Пароль: Запомнить:
Пользователи
Голосование

    Какую CMS Вы предпочитаете

    AtomX
    Fapos CMS
    Drunya CMS
Последние комментарии
Топ пользователей
Drunya
Репутация: 110
Сообщений: 3527
Сашка_из_Шебекино
Репутация: 87
Сообщений: 1803
boriska
Репутация: 65
Сообщений: 846
ARMI
Репутация: 46
Сообщений: 1858
BAH0
Репутация: 26
Сообщений: 544
С тех самых пор, как я начал свой путь в программирование, мне все и вся твердили о том, что в PHP совершенно не стоит думать о потреблении оперативной памяти сервера. Мол PHP сам с этим справляется на Ура. Но так ли оно на практике? Я решил провести серию небольших эксперементов, в основном, для тестирования Fapos CMS, но результаты оказались интересными. По крайней мере, мне так кажется. И я решил опубликовать их, хотя бы как напоминание самому себе. Ну и, за одно, может будет кому то полезно.

Для дальнейшего тестирования нам понадобятся отладочные функции, которые собственно и будут показывать разницу в памяти, между запуском приложения и нужной нам точки в коде.
 1 
 2 
 3 
 4 
 5 
 6 
<?php function memoryUsage($base_memory_usage) {
    
printf("Bytes diff: %s<br />\n"getSimpleFileSize(memory_get_usage() - $base_memory_usage));
}
function 
someBigValue() {
    return 
str_repeat('SOME BIG STRING'1024);
}
?>


А теперь, вот так - сразу, небольшой тест
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
<?php echo 'Start';
memoryUsage($memory);

$foo someBigValue();

echo 
'With foo';
memoryUsage($memory);

unset(
$foo);

echo 
'Unset foo';
memoryUsage($memory);?>

И вот, что мы получаем на выходе:
Start Bytes diff: 256
With foo Bytes diff: 15992
Unset foo Bytes diff: 616


Точные значения могут отличаться у вас, но тут главное заметить тенденцию. Сперва мы видим, что память практически свободна, но присвоение одной переменной обходится нам в 15 Кб. А ее удаление возвращает нам всю память. Ну почти всю. Что-то около 400 байт где-то потерялось. Тут надо бы сделать ремарку о том, как PHP хранит данные.

Переменная в PHP как бы состоит из двух частей: "имени", которое хранится в hash_table symbol_table, и "значения", которое хранится в zval контейнере. Такой механизм позволяет привязывать к одному значению несколько имен. Далее вы поймете, чем это удобно.

Если вернуться к моему примеру, то можно сказать, что мы высвободили память, хранившую значение нашей переменной, но после ее удаления, память для хранения ее имени не высвободилать. Это к стати и странно, так как такое пведение имело бы место, используй мы не unset(), а присвоение переменной значения NULL. Проверим:
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
<?php echo 'Start';
memoryUsage($memory);

$foo someBigValue();

echo 
'With foo';
memoryUsage($memory);

$foo null;

echo 
'Unset foo';
memoryUsage($memory);?>

И вот, что мы получаем на выходе:
Start Bytes diff: 256
With foo Bytes diff: 15992
Unset foo Bytes diff: 616


Обратите внимание, что unset() и NULL сработали идентично. Это из-за того, что тесты я провожу на древнем PHP. Начиная с версии 5.3 такое повдение уже не наблюдается, а unset() удаляет полностью всю переменную, а не только ее значение.


Массивы и память в PHP
Очень интересно себя ведут массивы. Дело в том, что при создании любой переменной, путем присвоения ей значения из другой переменной, для нее не выделяется новое место в памяти. Точнее для ее значения. Приведу пример:
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
<?php echo 'Start';
memoryUsage($memory);

$foo someBigValue();

echo 
'With foo';
memoryUsage($memory);

$bar $foo;
echo 
'With $bar';
memoryUsage($memory);

$bar strval($bar);
echo 
'With modified $bar';
memoryUsage($memory);

unset(
$foo$bar);
echo 
'Unset foo';
memoryUsage($memory);?>
Start Bytes diff: 312
With foo Bytes diff: 16032
With $bar Bytes diff: 16080
With modified $bar Bytes diff: 31456
Unset foo Bytes diff: 728

Как вы заметили, переменная $b выделила лишь память на свое имя, но не на значение. До того, как мы изменили значение $b, она просто ссылалась на значение $a. Вот такой вот встроеный механизм оптимизации PHP. Цель этого примера, была показать вам как это происходит с переменными, так как сейчас я покажу, что тоже самое происходит и с массивами, точнее их парами ключ - значение.
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
<?php $memory memory_get_usage();

echo 
'Start';
memoryUsage($memory);

$foo = array(someBigValue(), someBigValue(), someBigValue());

echo 
'With foo';
memoryUsage($memory);

$bar $foo;
echo 
'With $bar';
memoryUsage($memory);

$bar[0] = someBigValue();
echo 
'With modified $bar';
memoryUsage($memory);

unset(
$foo$bar);
echo 
'Unset foo';
memoryUsage($memory);?>
Start Bytes diff: 312
With foo Bytes diff: 47024
With $bar Bytes diff: 47096
With modified $bar Bytes diff: 62688
Unset foo Bytes diff: 1208


Обратите внимание, мы обновили, лишь один ключ массива $b и память выделилась только под него, остальные ключи так и продолжают ссылаться на значения $a.


Конечно, кто-то может сказать, что это лишние тонкости и все такое, но я на личном опыте убедился, что нехватка памяти это страшная штука. В маленьких скриптиках это может никогда не понадобиться, но если вы настроены заниматься серьезными проектами, то такие знания могут помочь вам с экономить долгие часы в поиске узких мест.

Так же я собираюсь плотно изучеть поведение PHP и памяти при работе с объектами, но это чуть позже.
Потребление памяти PHP. Оно существует

Теги: RAM memory PHP память и скрипты PHP;
Автор: Drunya
Категория: PHP
Просмотров: 3990
Комментариев: 5

Комментарии
  • User avatar

    ARMI

    Drunya, решил подколоть?)) Ну-ну)
    Дата отправления: 18 Янв 2012
  • User avatar

    Drunya

    не слышал о таком)))))
    Дата отправления: 18 Янв 2012
  • User avatar

    ARMI

    habrahabr.ru
    Дата отправления: 15 Янв 2012
  • User avatar

    Drunya

    Откуда, откуда ...? )))))))
    Дата отправления: 13 Янв 2012
  • User avatar

    skad0

    Кажется с хабра
    Дата отправления: 13 Янв 2012
Сейчас online: 3. Зарегистрированных: 0. Гостей: 3.
-->