Отслеживание использования памяти в PHP

Я пытаюсь отслеживать использование памяти сценария, обрабатывающего URL-адреса. Основная идея состоит в том, чтобы проверить, существует ли разумный буфер, прежде чем добавлять другой URL-адрес в обработчик cURL multi. Я использую концепцию «roll cURL», которая обрабатывает данные URL-адресов, когда выполняется многопроцессор. Это означает, что я могу поддерживать N соединений активными, добавляя новый URL-адрес из пула каждый раз, когда существующий URL-процесс обрабатывается и удаляется.

Я использовал memory_get_usage() с некоторыми положительными результатами. Добавление флага real_usage помогло (не совсем понятно различие между «системной» памятью и памятью «emalloc», но система показывает большие числа). memory_get_usage() работает с увеличением URL-адресов, а затем вниз, поскольку набор URL-адресов исчерпан. Тем не менее, я просто превысил ограничение 32M, когда моя последняя проверка памяти была ~ 18M.

Я обследую использование памяти каждый раз, когда сигналы cURL multi возвращают запрос. Поскольку несколько запросов могут возвращаться в одно и то же время, есть вероятность, что куча URL-адресов возвратит данные одновременно и фактически переместит использование памяти в 14M. Однако, если memory_get_usage() является точным, я предполагаю, что это то, что происходит.

[ Обновление : Должно было запускать больше тестов, прежде чем спросить, я думаю, увеличен лимит памяти php (но оставил «безопасную» сумму одинаковой в скрипте), а использование памяти, как сообщалось, перескочило с моего личного предела от 25M до более 32M , Затем, как и ожидалось, медленно уменьшались как URL-адреса, которые не были добавлены. Но я оставлю вопрос: это правильный способ сделать это?]

Могу ли я доверять memory_get_usage() таким образом? Есть ли лучшие альтернативные методы для использования памяти (я видел, как некоторые скрипты анализируют вывод команд оболочки)?

real_usage работает следующим образом:

Менеджер памяти Zend не использует системный malloc для каждого блока, в котором он нуждается. Вместо этого он выделяет большой блок системной памяти (с шагом 256 КБ, может быть изменен путем установки переменной среды ZEND_MM_SEG_SIZE ) и управляет ею внутри. Таким образом, есть два типа использования памяти:

  1. Сколько памяти двигатель взял из ОС («реальное использование»)
  2. Какая часть этой памяти фактически использовалась приложением («внутреннее использование»)

Любой из них может быть возвращен memory_get_usage() . Какой из них более полезен для вас, зависит от того, что вы изучаете. Если вы ищете оптимизацию кода в определенных частях, «внутренняя» может быть более полезной для вас. Если вы отслеживаете использование памяти во всем мире, «реальный» будет более полезен. memory_limit ограничивает «реальный» номер, поэтому, как только все блоки, которые разрешены лимитом, берутся из системы, а диспетчер памяти не может выделить запрошенный блок, распределение не выполняется. Обратите внимание, что «внутреннее» использование в этом случае может быть меньше предела, но распределение по-прежнему может завершиться неудачей из-за фрагментации.

Кроме того, если вы используете какой-либо инструмент для отслеживания внешней памяти, вы можете установить эту переменную среды USE_ZEND_ALLOC=0 которая отключит вышеуказанный механизм и заставит двигатель всегда использовать malloc() . Это будет иметь гораздо худшую производительность, но позволяет использовать инструменты отслеживания malloc.

См. Также статью об этом диспетчере памяти , также есть примеры кода.

Я также предполагаю, что memory_get_usage() безопасен, но я думаю, вы можете сравнить оба метода и решить сами, вот функция, которая анализирует системные вызовы:

 function Memory_Usage($decimals = 2) { $result = 0; if (function_exists('memory_get_usage')) { $result = memory_get_usage() / 1024; } else { if (function_exists('exec')) { $output = array(); if (substr(strtoupper(PHP_OS), 0, 3) == 'WIN') { exec('tasklist /FI "PID eq ' . getmypid() . '" /FO LIST', $output); $result = preg_replace('/[\D]/', '', $output[5]); } else { exec('ps -eo%mem,rss,pid | grep ' . getmypid(), $output); $output = explode(' ', $output[0]); $result = $output[1]; } } } return number_format(intval($result) / 1024, $decimals, '.', ''); } 

Ну, у меня никогда не было проблемы с памятью с моими PHP-скриптами, поэтому я не думаю, что мог бы помочь найти причину проблемы, но я могу рекомендовать, что вы получаете ускоритель PHP, вы заметите серьезное увеличение производительности и использование памяти со снижением. Вот список ускорителей и статья, сравнивающая некоторые из них (3-кратная производительность с любым из них)

Список Википедии

эталонный тест

Контрольные показатели – 2 года, но вы получаете представление о повышении производительности.

Если вам нужно, вы также можете увеличить лимит памяти в PHP, если у вас все еще есть проблемы даже с ускорителем. Откройте php.ini и найдите:

 memory_limit = 32M; 

и просто увеличьте его немного.