Я пытаюсь отслеживать использование памяти script, обрабатывающей URL-адреса. Основная идея состоит в том, чтобы проверить наличие разумного буфера перед добавлением другого URL-адреса в мультипроцессор cURL. Я использую концепцию "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 (но оставил "безопасную" сумму одинаковой в script), а использование памяти, как сообщалось, прыгать снизу ниже моего лимита в пределах от 25М до 32М. Затем, как и ожидалось, медленно уменьшались как URL-адреса, которые не были добавлены. Но я оставлю вопрос: это правильный способ сделать это?]
Могу ли я доверять memory_get_usage()
таким образом? Есть ли лучшие альтернативные методы для использования памяти (я видел, как некоторые скрипты анализируют вывод команд оболочки)?
Ответ 1
real_usage
работает следующим образом:
Менеджер памяти Zend не использует системный malloc для каждого блока, в котором он нуждается. Вместо этого он выделяет большой блок системной памяти (с шагом 256 КБ, может быть изменен путем установки переменной среды ZEND_MM_SEG_SIZE
) и управляет ею изнутри. Итак, есть два типа использования памяти:
- Сколько памяти, которую двигатель взял из ОС ( "реальное использование" )
- Какая часть этой памяти фактически использовалась приложением ( "внутреннее использование" )
Любой из них может быть возвращен memory_get_usage()
. Какой из них более полезен для вас, зависит от того, что вы изучаете. Если вы ищете оптимизацию кода в определенных частях, "внутренняя" может быть более полезной для вас. Если вы отслеживаете использование памяти во всем мире, "реальный" будет более полезен. memory_limit
ограничивает "реальный" номер, поэтому, как только все блоки, которые разрешены лимитом, берутся из системы, и диспетчер памяти не может выделить запрошенный блок, распределение не выполняется. Обратите внимание, что "внутреннее" использование в этом случае может быть меньше предела, но распределение по-прежнему может завершиться неудачей из-за фрагментации.
Кроме того, если вы используете инструмент отслеживания внешней памяти, вы можете установить это
переменная среды USE_ZEND_ALLOC=0
, которая отключит вышеуказанный механизм и заставит двигатель всегда использовать malloc()
. Это будет иметь гораздо худшую производительность, но позволяет использовать инструменты отслеживания malloc.
См. также статью об этом диспетчере памяти, также есть примеры кода.
Ответ 2
Я также предполагаю, что 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, '.', '');
}
Ответ 3
Ну, у меня никогда не было проблемы с памятью с моими PHP-сценариями, поэтому я не думаю, что мог бы помочь найти причину проблемы, но я могу рекомендовать, что вы получаете ускоритель PHP, вы заметите, что серьезное увеличение производительности и использование памяти со снижением. Вот список ускорителей и статья, сравнивающая некоторые из них (в 3 раза лучше, чем у любого из них)
Список Википедии
Benchmark
Тесты рассчитаны на 2 года, но вы получаете представление об увеличении производительности.
Если вам нужно, вы также можете увеличить лимит памяти в PHP, если у вас все еще есть проблемы даже с ускорителем. Откройте php.ini и найдите:
memory_limit = 32M;
и немного увеличьте его.