Php сколько памяти потребляет скрипт
Возвращает количество памяти в байтах, которое было выделено PHP-скрипту на данный момент.
Класс для получения времени выполнения скрипта
Очень простой класс, который можно использовать для получения времени выполнения скрипта PHP. Имеет приватное статическое свойство $start , в которой будет храниться время начала выполнения скрипта и имеющее значение по умолчанию $start = .0 . Метод start() присваивает значение, которое вернула функция microtime свойству $start . Метод finish() возвращает разницу между текущим временем (после выполнения скрипта) и тем, что мы зафиксировали при старте скрипта (присвоили значение в $start ).
Так используем класс:
Смотрите также
- memory_get_usage() - Возвращает количество памяти, выделенное для PHP
Список параметров
Передача true позволяет узнать реальное количество памяти, выделенной PHP скрипту системой, включая неиспользуемые страницы. Если аргумент не задан или равен false , будет возвращено только количество используемой памяти.
Замечание:
PHP не отслеживает память, которая выделялась не emalloc()
User Contributed Notes 1 note
memory_get_peak_usage() is used to retrieve the highest memory usage of PHP (or your running script) only. If you need the overall memory usage of the entire system, following function might be helpful. If retrieves the memory usage either in percent (without the percent sign) or in bytes by returning an array with free and overall memory of your system. Tested with Windows (7) and Linux (on an Raspberry Pi 2):
// Returns used memory (either in percent (without percent sign) or free and overall in bytes)
function getServerMemoryUsage ( $getPercentage = true )
$memoryTotal = null ;
$memoryFree = null ;
if ( stristr ( PHP_OS , "win" )) // Get total physical memory (this is in bytes)
$cmd = "wmic ComputerSystem get TotalPhysicalMemory" ;
@ exec ( $cmd , $outputTotalPhysicalMemory );
// Get free physical memory (this is in kibibytes!)
$cmd = "wmic OS get FreePhysicalMemory" ;
@ exec ( $cmd , $outputFreePhysicalMemory );
// Find free value
foreach ( $outputFreePhysicalMemory as $line ) if ( $line && preg_match ( "/^9+\$/" , $line )) $memoryFree = $line ;
$memoryFree *= 1024 ; // convert from kibibytes to bytes
break;
>
>
>
>
else
if ( is_readable ( "/proc/meminfo" ))
$stats = @ file_get_contents ( "/proc/meminfo" );
if ( $stats !== false ) // Separate lines
$stats = str_replace (array( "\r\n" , "\n\r" , "\r" ), "\n" , $stats );
$stats = explode ( "\n" , $stats );
// Separate values and find correct lines for total and free mem
foreach ( $stats as $statLine ) $statLineData = explode ( ":" , trim ( $statLine ));
//
// Extract size (TODO: It seems that (at least) the two values for total and free memory have the unit "kB" always. Is this correct?
//
// Total memory
if ( count ( $statLineData ) == 2 && trim ( $statLineData [ 0 ]) == "MemTotal" ) $memoryTotal = trim ( $statLineData [ 1 ]);
$memoryTotal = explode ( " " , $memoryTotal );
$memoryTotal = $memoryTotal [ 0 ];
$memoryTotal *= 1024 ; // convert from kibibytes to bytes
>
// Free memory
if ( count ( $statLineData ) == 2 && trim ( $statLineData [ 0 ]) == "MemFree" ) $memoryFree = trim ( $statLineData [ 1 ]);
$memoryFree = explode ( " " , $memoryFree );
$memoryFree = $memoryFree [ 0 ];
$memoryFree *= 1024 ; // convert from kibibytes to bytes
>
>
>
>
>
if ( is_null ( $memoryTotal ) || is_null ( $memoryFree )) return null ;
> else if ( $getPercentage ) return ( 100 - ( $memoryFree * 100 / $memoryTotal ));
> else return array(
"total" => $memoryTotal ,
"free" => $memoryFree ,
);
>
>
>
function getNiceFileSize ( $bytes , $binaryPrefix = true ) if ( $binaryPrefix ) $unit =array( 'B' , 'KiB' , 'MiB' , 'GiB' , 'TiB' , 'PiB' );
if ( $bytes == 0 ) return '0 ' . $unit [ 0 ];
return @ round ( $bytes / pow ( 1024 ,( $i = floor ( log ( $bytes , 1024 )))), 2 ) . ' ' . (isset( $unit [ $i ]) ? $unit [ $i ] : 'B' );
> else $unit =array( 'B' , 'KB' , 'MB' , 'GB' , 'TB' , 'PB' );
if ( $bytes == 0 ) return '0 ' . $unit [ 0 ];
return @ round ( $bytes / pow ( 1000 ,( $i = floor ( log ( $bytes , 1000 )))), 2 ) . ' ' . (isset( $unit [ $i ]) ? $unit [ $i ] : 'B' );
>
>
// Memory usage: 4.55 GiB / 23.91 GiB (19.013557664178%)
$memUsage = getServerMemoryUsage ( false );
echo sprintf ( "Memory usage: %s / %s (%s%%)" ,
getNiceFileSize ( $memUsage [ "total" ] - $memUsage [ "free" ]),
getNiceFileSize ( $memUsage [ "total" ]),
getServerMemoryUsage ( true )
);
?>
The function getNiceFileSize() is not required. Just used to shorten size in bytes.
На этот пост меня вдохновило исследование потребления памяти для моего текущего большого проекта на ZendFramework. Как обычно, по результатам исследования, я был шокирован нашей программистской самонадеянностью, которая нередко присутствует, когда мы пишем что-либо большое на PHP. Да и, наверное, не только на PHP.
Но обо всём по порядку.
Как будем измерять
Для начала определимся, как мы будем измерять «вес». Вот шаблон:
Такой шаблон подходит для измерения новой выделяемой памяти, то есть памяти под переменные. А вот измерить, сколько едят определения, то есть описания функций и классов, таким подходом нельзя, так как они заносятся в память до начала выполнения скрипта. Для того чтобы измерить определения, воспользуемся следующим шаблоном:
- Длины абсолютного пути до файла
- Каким по счёту этот файл был включён (каждые 8, 16, 32, 64 и т.д. идёт дополнительное выделение под внутренние структуры)
- Заполненностью внутренних структур самого PHP, которые периодически довыделяют себе памяти на будущее.
Сколько весят «объекты»
Можно заметить, что сборка Gentoo потребляет на 10-20% меньше памяти, а в редких случаях экономия доходит до 50%. Видимо, размер внутренних структур зависит от оптимизаций для процессора. Для экперимента я пересобирал php с разными вариантами CFLAGS, но он от этого не стал потреблять больше. Видимо разница проявляется не из-за пересборки самого PHP, а из пересборки стандартных Сишных библиотек.
Как было отмечено выше, точно измерить $include_overhead сложно, поэтому если вы запустите данные тесты, то у вас могут получится так, что потребление памяти будет прыгать на 4, 8, 12, 16 байт, даже в тестах, которые должны потреблять одинаково. Не стоит акцентировать на этом внимания. Я запускал тесты в разном порядке и более-менее установил истинное потребление памяти.
Поговорим о тестах, связанных с ZendFramework. Загрузка определений классов Zend`а в память отжирает существенные ресурсы, тогда как ссылки на объекты уже потребляют не так много. Controller2 нужен, чтобы проверить, сколько будет отжирать аналогичный контроллер, если все промежуточные классы уже в памяти. Model2 создана для этих же целей.
В потенциале использование PHP акселератора сэкономит нам память на всех определениях, ибо они уже будут храниться в памяти. Давайте проверим это утверждение.
Тестирование акселераторов
Для тестирования был взят APC, и тесты запускались через web с помощью скрипта:
Результаты приведены только тестов, где акселератор оказывает влияние:
myclass.a.empty | Описание класса A | 840 | 672 | 1480 | 1256 |
myclass.aa.interface | Описание интерфейса A | 856 | 676 | 1512 | 1264 |
myclass.ab.final | Описание финального класса AB | 844 | 672 | 1488 | 1256 |
myclass.ac.abstract | Описание абстрактного класса AC | 852 | 680 | 1504 | 1264 |
myclass.b.extended.empty | Описание класса B, расширяющего A | 912 | 700 | 1512 | 1264 |
myclass.c.empty.namespace | Описание пустого неймспейса C | 176 | -16 | 184 | -72 |
myclass.d.construct | Описание класса D с конструктором | 1256 | 960 | 2448 | 1736 |
myclass.dd.method | Описание класса DD с методом | 1268 | 968 | 2432 | 1728 |
myclass.ddd.private.var | Описание класса DDD с приватной переменной | 1140 | 964 | 2000 | 1760 |
myclass.dddd.public.var | Описание класса DDDD с публичной переменной | 1132 | 952 | 2000 | 1760 |
myclass.ddddd.static.var | Описание класса DDDDD со статической переменной | 1124 | 952 | 2000 | 1760 |
myclass.e.extended.destruct | Описание класса E с деструктором, расширяющим класс D | 1528 | 1228 | 2888 | 2160 |
myclass.z.free_memory | Удаление ссылок $e, $f | -332 | -548 | -784 | -1024 |
zend.a.init.autoload | Инициализация autoload для ZendFramework | 127 596 | 16 196 | 276 440 | 28 992 |
zend.a.init.model | Инициализация адаптера по умолчанию для базы | 1 018 564 | 251 840 | 2 081 696 | 479 280 |
zend.extended.controller1 | Определение контроллера от Zend_Controller_Action. Попутно происходит подгрузка стандартных зендовских классов | 378 464 | 66 804 | 809 608 | 120 864 |
zend.extended.controller2 | Определение контроллера. Класы Zend уже подгружены, смотрим сколько весит наш класс | 11 476 | 11 140 | 19 792 | 19 056 |
zend.extended.model1 | Определение модели от Zend_Db_Table. Попутно происходит подгрузка стандартных зендовских классов. | 28 080 | 25 676 | 48 704 | 42 944 |
zend.extended.model2 | Определение модели. Класы Zend уже подгружены, смотрим, сколько весит наш класс | 28 080 | 25 704 | 48 672 | 42 960 |
Я также производил некоторые тесты с xcache и заметил 2 отличия от APC. Во-первых: xcache проигрывает (почти всегда) на 10-15% по экономии памяти. А во-вторых: xcache сразу отдаёт файлы из кеша, тогда как APC — только после повторного обращения. Хоть и бесполезное, но преимущество.
Сразу отмечу, в результатах разброс гораздо больше, чем при тестировании без акселератора, поскольку файлы не переименовывались и $include_overhead рассчитывался с большой ошибкой.
Как мы видим, акселератор хоть и экономит нам память для определений, но не полностью, поскольку PHP, видимо, переносит какие-то куски из кеша в текущую сессию.
Теперь перейдем от абстрактных тестов к вполне реальным.
Тестирование небольшого приложения на ZendFramework
Для тестирования было взято тестовое задание одного из наших программистов (Simple-blog): сервис коллективного блога с функциями: регистрации, авторизации, чтения списка постов, открытия поста и его комментирования. В конце index.php было написано:
чтобы проверить, какое максимальное количество памяти пожирал скрипт во время генерации страницы. Результаты:
Список постов | 5 328 648 | 1 792 968 | 10 938 160 | 3 306 720 |
Пост и его коментарии | 5 372 356 | 1 831 452 | 11 015 320 | 3 373 528 |
Логин форма | 6 781 656 | 2 277 164 | 13 982 104 | 4 187 600 |
Форма регистрации | 6 796 496 | 2 291 568 | 14 009 384 | 4 211 432 |
Дополнительно проверялась сборка под Gentoo, он оказался на 25% эффективнее во всех тестах.
Выводы
- Если память дорогой ресурс (например VPS) и не особо нужны 64-битные числа, то есть смысл использовать 32-битную версию ОС. Выигрыш будет ~ в 1.8 раза.
- В ОС, в которых происходит заточка пакетов под текущую архитектуру можно дополнительно сэкономить 25% памяти.
- Ничто так не потребляет память в PHP, как тяжёлый фреймворк. Использование акселератора не спасает от поедания памяти тяжёлыми фреймворками. Возможно имеет смысл ознакомиться со следующим сравнением PHP фреймворков, чтобы выбрать для себя баланс популярности/производительности.
- Ситуацию, которая изображена на картинке для привлечения внимания, можно получить, если размер APC кеша окажется исчерпан. Этого добиться не сложно, если у вас много сайтов на одной машине, а вы установили APC, не проверяя хватит ли вам памяти. При этом статистика (apc.php) вам будет сообщать, что у вас есть ещё около 40% памяти, но ей особо не следует верить, ибо у APC плохой менеджер памяти и он просто не умеет использовать её эффективно. Лучше всегда обращайте внимание на hits и miss значения.
Кодяра
AntonShevchuk добавил результаты для тестов на PHP 5.4. PHP 5.4 выглядит гораздо экономичнее по сравнению с 5.3. Официальная документация это также подтверждает.
Несколько способов узнать время выполнения скрипта PHP и затраченный объем памяти при выполнении этого скрипта.
Время выполнения скрипта
Функция microtime() с переданным значением true возвращает число секунд, прошедших с полуночи 01.01.1970 , причём это значение подсчитано до сотых долей секунды. Затем идёт сам скрипт (исполняемый код), который мы и проверяем. В последней строкой будет разница между текущим временем (после выполнения скрипта) и тем, что мы зафиксировали при старте скрипта. Разница времени после выполнения скрипта и времени до начала его работы, и есть время выполнения скрипта.
Можно вместо $start = microtime(true) брать значение из переменной $_SERVER['REQUEST_TIME_FLOAT'] , которая содержит время запроса к серверу. Вычисление времени выполнения происходит за исполняемым кодом.
Если на сервере установлен Xdebag :
Можно подсчитать среднее значение выполнения скрипта и записать результат в логи:
Уменьшение размера используемой памяти
Прежде всего, основной причиной реализации механизма сборки мусора является уменьшение размера используемой памяти с помощью чистки циклических ссылок, которая происходит при достижении соответствующих условий. В реализации PHP это происходит как только заполнится корневой буфер или при вызове функции gc_collect_cycles() . На графике ниже приведено использование памяти скрипта, запущенного в PHP 5.2 и PHP 5.3, без учёта памяти, используемой самим PHP при запуске.
for ( $i = 0 ; $i $a = new Foo ;
$a -> self = $a ;
if ( $i % 500 === 0 )
echo sprintf ( '%8d: ' , $i ), memory_get_usage () - $baseMemory , "\n" ;
>
>
?>
В этом очень академическом примере мы создаём объект, свойство a которого задаётся ссылкой на сам объект. Когда в скрипте в следующей итерации цикла переопределяется переменная $a , то происходит типичная утечка памяти. В данном случае пропадают два контейнера zval (контейнер объекта и контейнер свойства объекта), но определяется только один корень - удалённая переменная. Как только пройдут 10 000 итераций (максимально в корневом буфере будет 10 000 корней), то запустится механизм сборки мусора и память, занимаемая этими корнями, будет освобождена. Этот процесс хорошо виден на графике использования памяти для PHP 5.3: после каждых 10 000 итераций график проседает. Сам по себе механизм в данном примере совершает не так много работы, потому что структура утечек слишком проста. Из графика видно, что максимальное использование памяти в PHP 5.3 составило около 9 Мб, тогда как в PHP 5.2 оно продолжает возрастать.
Внутренняя статистика сборщика мусора
Можно получить немного больше информации о том, как механизм сборки мусора выполняется в PHP. Но для этого вам необходимо пересобрать PHP для включения теста производительности и кода для дополнительного сбора данных. Необходимо установить переменную окружения CFLAGS в значение -DGC_BENCH=1 до выполнения команды ./configure с вашими параметрами. Следующие команды должны сработать:
При запуске вышеприведённого примера с обновлённым PHP, можно увидеть следующую информацию по завершении работы скрипта:
Наиболее полезная статистика отображена в первом блоке. Можно увидеть, что механизм сборки мусора был запущен 110 раз, и суммарно было освобождено свыше 2 миллионов записей в памяти. Если сборка мусора была запущена хотя бы раз, то максимальное число корней в буфере всегда будет равно 10 000.
Список параметров
Передача true в качестве этого аргумента позволяет получить реальный объем памяти, выделенный системой. Если аргумент не задан или равен false , возвращаются сведения только о памяти, выделенной функцией emalloc() .
Заключение
В целом, сборщик мусора в PHP вызовет ощутимые замедления только во время непосредственной работы механизма сборки циклических ссылок, тогда как в обычных (небольших) скриптах не должно быть никакого падения производительности.
Однако в тех случаях, когда механизм сборки должен срабатывать и в обычных скриптах, снижение используемой памяти позволяет одновременно работать на сервере большему их количеству.
Преимущества наиболее очевидны для долгоработающих скриптов, таких как большие наборы тестов или демоны. Новый механизм также должен снизить утечки памяти для приложений » PHP-GTK, которые выполняются обычно дольше, чем веб-скрипты.
Возвращает максимальный объем памяти в байтах, который был выделен PHP-скрипту.
Объем использованной памяти
Функция memory_get_usage() возвращает количество памяти в байтах, которое было выделено PHP скрипту на данный момент.
Принцип очень похож на измерение времени выполнения скрипта, о котором речь шла выше. Здесь тоже есть, как бы, стартовое состояние и и разница между текущим состоянием и стартовым.
В Xdebug есть функция xdebug_memory_usage() , которая возвращает тот же результат.
Возвращаемые значения
Возвращает максимальный объем памяти в байтах.
Примеры
// Это просто пример, цифры ниже будут
// отличаться в зависимости от вашей системы
echo memory_get_usage () . "\n" ; // 36640
$a = str_repeat ( "Hello" , 4242 );
echo memory_get_usage () . "\n" ; // 57960
echo memory_get_usage () . "\n" ; // 36744
Замедление работы
Второй областью, где сборка мусора влияет на производительность, является потеря времени, когда сборщик мусора освобождает память. Чтобы понять степень этого влияния, мы немного изменим предыдущий скрипт, добавив большее число итераций и промежуточных переменных. Изменённый скрипт:
echo memory_get_peak_usage (), "\n" ;
?>
Мы запустим скрипт два раза: с включённой опцией zend.enable_gc и без неё.
На тестовой машине первая команда примерно выполняется 10.7 секунд, а вторая примерно 11.4 секунды. Это примерно на 7% медленнее. Однако, максимальное использование памяти скриптом уменьшилось на 98% с 931 Мб до 10 Мб. Этот тест не очень научный, но он действительно демонстрирует преимущество по использованию памяти, обеспечиваемое сборщиком мусора. Также хорошо то, что замедление для этого скрипта всегда примерно 7%, тогда как экономия памяти увеличивается все больше и больше при нахождении нового мусора.
Смотрите также
- memory_get_peak_usage() - Возвращает пиковое значение объёма памяти, выделенное PHP
Список параметров
Передача true позволяет узнать реальное количество памяти, выделенной PHP скрипту системой, включая неиспользуемые страницы. Если аргумент не задан или равен false , будет возвращено только количество используемой памяти.
Замечание:
PHP не отслеживает память, которая выделялась не emalloc()
Возвращаемые значения
Возвращает количество памяти в байтах.
User Contributed Notes 15 notes
To get the memory usage in KB or MB
function convert ( $size )
$unit =array( 'b' , 'kb' , 'mb' , 'gb' , 'tb' , 'pb' );
return @ round ( $size / pow ( 1024 ,( $i = floor ( log ( $size , 1024 )))), 2 ). ' ' . $unit [ $i ];
>
echo convert ( memory_get_usage ( true )); // 123 kb
?>
Note, that the official IEC-prefix for kilobyte, megabyte and so on are KiB, MiB, TiB and so on.
At first glance this may sound like "What the hell? Everybody knows, that we mean 1024 not 1000 and the difference is not too big, so what?". But in about 10 years, the size of harddisks (and files on them) reaches the petabyte-limit and then the difference between PB and PiB is magnificent.
Better to get used to it now. :)
To get the memory usage in KB or MB
function echo_memory_usage () <
$mem_usage = memory_get_usage ( true );
if ( $mem_usage < 1024 )
echo $mem_usage . " bytes" ;
elseif ( $mem_usage < 1048576 )
echo round ( $mem_usage / 1024 , 2 ). " kilobytes" ;
else
echo round ( $mem_usage / 1048576 , 2 ). " megabytes" ;
memory_get_usage() is used to retrieve the memory allocated to PHP only (or your running script). But intuitively, many people expect to get the memory usage of the system, based on the name of the function.
So if you need the overall memory usage, following function might be helpful. If retrieves the memory usage either in percent (without the percent sign) or in bytes by returning an array with free and overall memory of your system. Tested with Windows (7) and Linux (on an Raspberry Pi 2):
// Returns used memory (either in percent (without percent sign) or free and overall in bytes)
function getServerMemoryUsage ( $getPercentage = true )
$memoryTotal = null ;
$memoryFree = null ;
if ( stristr ( PHP_OS , "win" )) // Get total physical memory (this is in bytes)
$cmd = "wmic ComputerSystem get TotalPhysicalMemory" ;
@ exec ( $cmd , $outputTotalPhysicalMemory );
// Get free physical memory (this is in kibibytes!)
$cmd = "wmic OS get FreePhysicalMemory" ;
@ exec ( $cmd , $outputFreePhysicalMemory );
// Find free value
foreach ( $outputFreePhysicalMemory as $line ) if ( $line && preg_match ( "/^9+\$/" , $line )) $memoryFree = $line ;
$memoryFree *= 1024 ; // convert from kibibytes to bytes
break;
>
>
>
>
else
if ( is_readable ( "/proc/meminfo" ))
$stats = @ file_get_contents ( "/proc/meminfo" );
if ( $stats !== false ) // Separate lines
$stats = str_replace (array( "\r\n" , "\n\r" , "\r" ), "\n" , $stats );
$stats = explode ( "\n" , $stats );
// Separate values and find correct lines for total and free mem
foreach ( $stats as $statLine ) $statLineData = explode ( ":" , trim ( $statLine ));
//
// Extract size (TODO: It seems that (at least) the two values for total and free memory have the unit "kB" always. Is this correct?
//
// Total memory
if ( count ( $statLineData ) == 2 && trim ( $statLineData [ 0 ]) == "MemTotal" ) $memoryTotal = trim ( $statLineData [ 1 ]);
$memoryTotal = explode ( " " , $memoryTotal );
$memoryTotal = $memoryTotal [ 0 ];
$memoryTotal *= 1024 ; // convert from kibibytes to bytes
>
// Free memory
if ( count ( $statLineData ) == 2 && trim ( $statLineData [ 0 ]) == "MemFree" ) $memoryFree = trim ( $statLineData [ 1 ]);
$memoryFree = explode ( " " , $memoryFree );
$memoryFree = $memoryFree [ 0 ];
$memoryFree *= 1024 ; // convert from kibibytes to bytes
>
>
>
>
>
if ( is_null ( $memoryTotal ) || is_null ( $memoryFree )) return null ;
> else if ( $getPercentage ) return ( 100 - ( $memoryFree * 100 / $memoryTotal ));
> else return array(
"total" => $memoryTotal ,
"free" => $memoryFree ,
);
>
>
>
function getNiceFileSize ( $bytes , $binaryPrefix = true ) if ( $binaryPrefix ) $unit =array( 'B' , 'KiB' , 'MiB' , 'GiB' , 'TiB' , 'PiB' );
if ( $bytes == 0 ) return '0 ' . $unit [ 0 ];
return @ round ( $bytes / pow ( 1024 ,( $i = floor ( log ( $bytes , 1024 )))), 2 ) . ' ' . (isset( $unit [ $i ]) ? $unit [ $i ] : 'B' );
> else $unit =array( 'B' , 'KB' , 'MB' , 'GB' , 'TB' , 'PB' );
if ( $bytes == 0 ) return '0 ' . $unit [ 0 ];
return @ round ( $bytes / pow ( 1000 ,( $i = floor ( log ( $bytes , 1000 )))), 2 ) . ' ' . (isset( $unit [ $i ]) ? $unit [ $i ] : 'B' );
>
>
// Memory usage: 4.55 GiB / 23.91 GiB (19.013557664178%)
$memUsage = getServerMemoryUsage ( false );
echo sprintf ( "Memory usage: %s / %s (%s%%)" ,
getNiceFileSize ( $memUsage [ "total" ] - $memUsage [ "free" ]),
getNiceFileSize ( $memUsage [ "total" ]),
getServerMemoryUsage ( true )
);
?>
The function getNiceFileSize() is not required. Just used to shorten size in bytes.
[EDIT by danbrown AT php DOT net: This is intended by the author to only be used with PHP 4 < 4.3.2.]
I'd just like to point out that although sandeepc at myrealbox dot com's idea for displaying the current memory usage is a good one, it's perhaps a bad idea to pipe the entire process list through grep. A better performing method would be to select only the process we're interested in:
$pid = getmypid ();
error_log ( 'MEMORY USAGE (% KB PID ): ' . ` ps --pid $pid --no-headers -o%mem,rss,pid `);
?>
True, it's not much of a performance boost, but every bit helps.
I can confirm that this function triggers a garbage collection. I have a script that exceeded 128MB of memory at some point and ended with a fatal error. I was confused, because the script dealt with some large files initially, but the memory load from that point on should have been marginal, and the error occurred at the very end.
Those large files were dealt in a dedicated function and i even used unset() on the variable holding the file after the file was written to disk inside that function. So the memory should have been cleared twice, first after the unset() call, and second once the function ended.
To debug the memory usage, I called memory_get_usage(true) at some points and echo-ed the memory allocation. Just by adding a few echos here and there in the script, the memory usage never exceeded 1MB overhead (on top of the current file size) and the memory error disappeared.
The method sandeepc at myrealbox dot com posted yields larger memory usage, my guess is that it includes all the PHP interpreter/internal code and not just the script being run.
1) Use ps command
MEMORY USAGE (% KB PID ): 0.8 12588 25087 -> about 12MB
2) Use memory_get_usage()
int(6041952) -> about 6MB
This is a function that should work for both Windows XP/2003 and most distrabutions of UNIX and Mac OS X.
return preg_replace ( '/[\D]/' , '' , $output [ 5 ] ) * 1024 ;
>
>else
<
//We now assume the OS is UNIX
//Tested on Mac OS X 10.4.6 and Linux Red Hat Enterprise 4
//This should work on most UNIX systems
$pid = getmypid ();
exec ( "ps -eo%mem,rss,pid | grep $pid " , $output );
$output = explode ( " " , $output [ 0 ]);
//rss is given in 1024 byte units
return $output [ 1 ] * 1024 ;
>
>
>
?>
Note that the description for `memory_get_usage` is different than it's default parameter!
"`int memory_get_usage ([ bool $real_usage = FALSE ] )`
Returns the amount of memory, in bytes, that's currently being allocated to your PHP script. "
Default parameter = `FALSE`
WRONG description: Returns the amount of memory, in bytes, that's currently being allocated to your PHP script.
It must be: Returns the amount of memory, in bytes, that's currently used by your PHP script.
[EDIT by danbrown AT php DOT net: This function will only extend Windows versions of PHP where the server has the required third-party software.]
I was unable to get the previous examples working properly and created code which works at least for me. Enjoy!
// try to use PHP build in function
if( function_exists ( 'memory_get_usage' ) ) <
return memory_get_usage ();
>
// Try to get Windows memory usage via pslist command
if ( substr ( PHP_OS , 0 , 3 ) == 'WIN' )
$resultRow = 8 ;
$resultRowItemStartPosition = 34 ;
$resultRowItemLength = 8 ;
$output = array();
exec ( 'pslist -m ' . getmypid () , $output );
return trim ( substr ( $output [ $resultRow ], $resultRowItemStartPosition , $resultRowItemLength )) . ' KB' ;
// No memory functionality available at all
return 'no value' ;
В предыдущем разделе нами уже говорилось, что простой сбор корней меньше влияет на производительность. Хотя запись корней в буфер по сравнению с полным отсутствием таковой в PHP 5.2 работает медленней, другие изменения в работе PHP 5.3 сделали эту потерю производительности незаметной.
Есть две основные области влияющие на производительность: уменьшение размера используемой памяти и замедление работы при сборке мусора. Рассмотрим их.
Читайте также: