Голосование
Какую CMS Вы предпочитаете
AtomX
Fapos CMS
Drunya CMS
Топ новостей
- Генератор аватарок в стиле пиксель-арт
- Скачать Fapos CMS 1.1.8 Бесплатно
- Цунами в Японии. Последствия.
- Предварительная инфа о FAPOS 1.1.9. Часть 2
- Описание версии CMS Fapos 0.9.9
- Новая версия Fapos 1.3
- Половина россиян не смогла отличить легальный контент
- Что есть Fapos CMS
- Убийца Apache у вас на пороге
- Открытое тестирование Fapos 0.9.9
Последние комментарии
Топ пользователей
Сайты на AtomX CMS
С тех самых пор, как я начал свой путь в программирование, мне все и вся твердили о том, что в PHP совершенно не стоит думать о потреблении оперативной памяти сервера. Мол PHP сам с этим справляется на Ура. Но так ли оно на практике? Я решил провести серию небольших эксперементов, в основном, для тестирования Fapos CMS, но результаты оказались интересными. По крайней мере, мне так кажется. И я решил опубликовать их, хотя бы как напоминание самому себе. Ну и, за одно, может будет кому то полезно.
Для дальнейшего тестирования нам понадобятся отладочные функции, которые собственно и будут показывать разницу в памяти, между запуском приложения и нужной нам точки в коде.
А теперь, вот так - сразу, небольшой тест
И вот, что мы получаем на выходе:
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. Проверим:
И вот, что мы получаем на выходе:
Start Bytes diff: 256
With foo Bytes diff: 15992
Unset foo Bytes diff: 616
Обратите внимание, что unset() и NULL сработали идентично. Это из-за того, что тесты я провожу на древнем PHP. Начиная с версии 5.3 такое повдение уже не наблюдается, а unset() удаляет полностью всю переменную, а не только ее значение.
Массивы и память в PHP
Очень интересно себя ведут массивы. Дело в том, что при создании любой переменной, путем присвоения ей значения из другой переменной, для нее не выделяется новое место в памяти. Точнее для ее значения. Приведу пример:
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. Цель этого примера, была показать вам как это происходит с переменными, так как сейчас я покажу, что тоже самое происходит и с массивами, точнее их парами ключ - значение.
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 и памяти при работе с объектами, но это чуть позже.
Для дальнейшего тестирования нам понадобятся отладочные функции, которые собственно и будут показывать разницу в памяти, между запуском приложения и нужной нам точки в коде.
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);?>
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);?>
With foo Bytes diff: 47024
With $bar Bytes diff: 47096
With modified $bar Bytes diff: 62688
Unset foo Bytes diff: 1208
Обратите внимание, мы обновили, лишь один ключ массива $b и память выделилась только под него, остальные ключи так и продолжают ссылаться на значения $a.
Конечно, кто-то может сказать, что это лишние тонкости и все такое, но я на личном опыте убедился, что нехватка памяти это страшная штука. В маленьких скриптиках это может никогда не понадобиться, но если вы настроены заниматься серьезными проектами, то такие знания могут помочь вам с экономить долгие часы в поиске узких мест.
Так же я собираюсь плотно изучеть поведение PHP и памяти при работе с объектами, но это чуть позже.
Комментарии
-
ARMI
Drunya, решил подколоть?)) Ну-ну)Дата отправления: 18 Янв 2012 -
Drunya
не слышал о таком)))))Дата отправления: 18 Янв 2012 -
ARMI
habrahabr.ruДата отправления: 15 Янв 2012 -
Drunya
Откуда, откуда ...? )))))))Дата отправления: 13 Янв 2012 -
skad0
Кажется с хабраДата отправления: 13 Янв 2012
Сейчас online: 52. Зарегистрированных: 1. Гостей: 51.
AtomX 2.8 Beta - Новая версия бесплатной CMS
AtomX 2.8 Beta - Новая версия бесплатной CMS
Программирование - что может быть проще.
Программирование - что может быть проще.
AtomX 2.8 Beta - Новая версия бесплатной CMS
AtomX 2.8 Beta - Новая версия бесплатной CMS
Написание простого вируса в блокноте
Что такое API и для чего они нужны
Классы в PHP для чайников
Написание простого вируса в блокноте