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 "Данные о потоке недоступны в этой системе";
}
?>Данные о потоке недоступны в этой системе
Функция microtime(true) возвращает временную метку с микросекундной точностью. Подходит для замеров общего времени выполнения участка кода, но не разделяет пользовательское и системное время процессора.
Эти функции предоставляют информацию об использовании оперативной памяти скриптом, что является другой важной метрикой производительности. 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). Ранее функция работала только с процессами.
<?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
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с)
Показатели ru_minflt и ru_majflt могут указывать на интенсивность работы с памятью.
<?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
Модуль resource предоставляет очень похожую функцию. Структура возвращаемых данных аналогична.
import resource
usage = resource.getrusage(resource.RUSAGE_SELF)
print(f"Пользовательское время: {usage.ru_utime}")
print(f"Системное время: {usage.ru_stime}")Пользовательское время: 0.032 Системное время: 0.008
В Node.js доступен метод объекта process. Он возвращает объект с метриками, включая использование CPU в микросекундах.
const usage = process.resourceUsage();
console.log(`Пользовательское CPU время: ${usage.userCPUTime}`);
console.log(`Системное CPU время: ${usage.systemCPUTime}`);Пользовательское CPU время: 15625 Системное CPU время: 3125
Прямого аналога нет. Для анализа запросов используют SHOW PROFILE, EXPLAIN ANALYZE или таблицы INFORMATION_SCHEMA.PROFILING, которые дают детали выполнения по времени, но не общие метрики процесса.