Отслеживание использования памяти в PHP - PullRequest
32 голосов
/ 18 февраля 2010

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

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

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

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

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

Ответы [ 4 ]

45 голосов
/ 18 февраля 2010

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

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

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

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

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

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

8 голосов
/ 18 февраля 2010

Я также предполагаю, что 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, '.', '');
}
1 голос
/ 19 февраля 2018

Используйте xdebug , поскольку оно было недавно (29 января) обновлено и теперь включает информацию о профилировании памяти. Он отслеживает вызовы функций и сколько памяти они потребляют. Это позволяет вам получить очень глубокое представление о вашем коде и, по крайней мере, направить вас к осознанию проблем.

Документация полезна, но, по сути, вы, установите ее, включите профилирование xdebug.profiler_enable = 1 и передайте вывод xdebug.profiler_output_dir=/some/path инструменту, такому как qcachegrind , для выполнения тяжелой работы, позволяя визуально увидеть ее.

0 голосов
/ 18 февраля 2010

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

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

Benchmark

Тестам уже 2 года, но вы получаете представление об увеличении производительности.

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

memory_limit = 32M;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...