Getrusage: примеры (PHP)

Анализ ресурсов процесса с getrusage в PHP
Раздел: Информация о системе
getrusage(int $who = 0): array|false

Функция getrusage() в PHP предоставляет доступ к статистике об использовании ресурсов текущим процессом или его завершенными дочерними процессами. Эта информация полезна для профилирования, отладки производительности и мониторинга потребления системных ресурсов скриптом.

Назначение и сценарии использования

Функция чаще применяется для анализа временных затрат (пользовательское и системное время процессора) и отслеживания ряда системных вызовов, например, количества обращений к диску или сетевых операций. Это позволяет выявлять узкие места в коде.

Аргументы функции

Функция принимает один необязательный аргумент:

  • $mode (int): Определяет, информацию о каком процессе вернуть. Принимает одну из констант:
    • RUSAGE_SELF (0) - Возвращает данные о текущем процессе (по умолчанию).
    • RUSAGE_CHILDREN (1) - Возвращает совокупные данные обо всех завершенных дочерних процессах.
    • RUSAGE_THREAD (2) - Возвращает данные о текущем потоке (доступно на некоторых системах, например, Linux).

Функция возвращает ассоциативный массив с различными метриками или false в случае ошибки. Состав и наличие ключей в массиве зависят от операционной системы.

Простые варианты использования

Базовый вызов для получения данных о текущем процессе:

<?php
$usage = getrusage();
print_r($usage);
?>
Array
(
    [ru_utime.tv_sec] => 0
    [ru_utime.tv_usec] => 20000
    [ru_stime.tv_sec] => 0
    [ru_stime.tv_usec] => 10000
    [ru_maxrss] => 12632
    [ru_ixrss] => 0
    [ru_idrss] => 0
    [ru_isrss] => 0
    [ru_minflt] => 810
    [ru_majflt] => 0
    [ru_nswap] => 0
    [ru_inblock] => 0
    [ru_oublock] => 0
    [ru_msgsnd] => 0
    [ru_msgrcv] => 0
    [ru_nsignals] => 0
    [ru_nvcsw] => 3
    [ru_nivcsw] => 0
)

Получение данных только о завершенных дочерних процессах:

<?php
// Пример с запуском внешней команды
shell_exec('sleep 1');
$childUsage = getrusage(RUSAGE_CHILDREN);
echo "Пользовательское время детей: {$childUsage['ru_utime.tv_usec']} мкс";
?>
Пользовательское время детей: 0 мкс

Попытка получить данные о потоке:

<?php
$threadUsage = getrusage(RUSAGE_THREAD);
if ($threadUsage) {
    echo "Данные потока получены";
} else {
    echo "Данные о потоке недоступны в этой системе";
}
?>
Данные о потоке недоступны в этой системе
Похожие функции в PHP
microtime()

Функция microtime(true) возвращает временную метку с микросекундной точностью. Подходит для замеров общего времени выполнения участка кода, но не разделяет пользовательское и системное время процессора.

memory_get_usage() и memory_get_peak_usage()

Эти функции предоставляют информацию об использовании оперативной памяти скриптом, что является другой важной метрикой производительности. getrusage() также возвращает похожий показатель ru_maxrss (максимальный размер резидентного набора).

Выбор функции

getrusage() предпочтительнее для детального анализа времени CPU и операций ввода-вывода на системном уровне. microtime() проще для измерения общего хронометража. Функции памяти дают более точные и кросс-платформенные данные об использовании RAM.

Частые ошибки
Неверная интерпретация времени

Время возвращается в секундах и микросекундах отдельно. Ошибкой является попытка использовать только одно значение.

<?php
$ru = getrusage();
// Неправильно:
$total_time = $ru['ru_utime.tv_sec']; // Теряем микросекунды
// Правильно:
$user_time = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1000000;
echo "Пользовательское время: $user_time сек";
?>
Пользовательское время: 0.021543 сек
Ожидание данных от незавершенных дочерних процессов

RUSAGE_CHILDREN включает данные только о тех процессах, которые были завершены и ожиданы с помощью функций типа pcntl_waitpid(). Данные о еще работающих детях не отображаются.

Игнорирование платформенных различий

Многие ключи массива (например, ru_ixrss, ru_msgrcv) могут быть нулевыми или отсутствовать в зависимости от ОС. Код не должен жестко зависеть от их наличия.

История изменений

В PHP 8.1.0 была добавлена поддержка константы RUSAGE_THREAD для получения статистики по текущему потоку. Однако эта возможность зависит от поддержки со стороны базовой операционной системы и может быть недоступна (например, в Windows). Ранее функция работала только с процессами.

Сложные и специальные примеры
Расчет общего времени CPU процесса
Пример php
<?php
function getCpuTime() {
    $ru = getrusage();
    $userTime = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6;
    $sysTime = $ru['ru_stime.tv_sec'] + $ru['ru_stime.tv_usec'] / 1e6;
    return $userTime + $sysTime;
}
$startCpu = getCpuTime();
// Имитация нагрузки
for ($i = 0; $i < 1000000; $i++) { md5($i); }
$endCpu = getCpuTime();
echo sprintf("Цикл использовал %.4f секунд CPU\n", $endCpu - $startCpu);
?>
Цикл использовал 0.2543 секунд CPU
Сравнение производительности двух алгоритмов
Пример php
<?php
function measureAlgo($name, callable $algo) {
    $start = getrusage();
    $result = $algo();
    $end = getrusage();
    $time = ($end['ru_utime.tv_sec'] - $start['ru_utime.tv_sec']) +
            ($end['ru_utime.tv_usec'] - $start['ru_utime.tv_usec']) / 1e6;
    echo "$name: $result (время: {$time}с)\n";
}
measureAlgo('Сумма циклом', function() {
    $sum = 0;
    for($i=0; $i<1e6; $i++) $sum += $i;
    return $sum;
});
measureAlgo('Формула Гаусса', function() {
    $n = 1e6;
    return $n * ($n - 1) / 2;
});
?>
Сумма циклом: 499999500000 (время: 0.028167с)
Формула Гаусса: 499999500000 (время: 7.0E-6с)
Мониторинг страничных сбоев (page faults)

Показатели ru_minflt и ru_majflt могут указывать на интенсивность работы с памятью.

Пример php
<?php
$ru_before = getrusage();
// Создаем большую структуру данных
$bigArray = range(1, 1000000);
$ru_after = getrusage();
$minor_faults = $ru_after['ru_minflt'] - $ru_before['ru_minflt'];
echo "Незначительных страничных сбоев: $minor_faults\n";
?>
Незначительных страничных сбоев: 2145
Аналоги в других языках
Python: resource.getrusage()

Модуль resource предоставляет очень похожую функцию. Структура возвращаемых данных аналогична.

import resource
usage = resource.getrusage(resource.RUSAGE_SELF)
print(f"Пользовательское время: {usage.ru_utime}")
print(f"Системное время: {usage.ru_stime}")
Пользовательское время: 0.032
Системное время: 0.008
JavaScript (Node.js): process.resourceUsage()

В Node.js доступен метод объекта process. Он возвращает объект с метриками, включая использование CPU в микросекундах.

const usage = process.resourceUsage();
console.log(`Пользовательское CPU время: ${usage.userCPUTime}`);
console.log(`Системное CPU время: ${usage.systemCPUTime}`);
Пользовательское CPU время: 15625
Системное CPU время: 3125
MySQL: Информационные схемы и PROFILING

Прямого аналога нет. Для анализа запросов используют SHOW PROFILE, EXPLAIN ANALYZE или таблицы INFORMATION_SCHEMA.PROFILING, которые дают детали выполнения по времени, но не общие метрики процесса.

PHP getrusage function comments

En
Getrusage Gets the current resource usages