PHP getrusage () возвращает неверную информацию? - PullRequest
4 голосов
/ 28 апреля 2010

Я пытаюсь определить использование процессора моими PHP-скриптами. Я только что нашел эту статью , в которой подробно рассказывается, как найти время загрузки системного и пользовательского ЦП (раздел 4).

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

Первый пример :

sleep(3);

$data = getrusage();
echo "User time: ".
    ($data['ru_utime.tv_sec'] +
    $data['ru_utime.tv_usec'] / 1000000);
echo "System time: ".
    ($data['ru_stime.tv_sec'] +
    $data['ru_stime.tv_usec'] / 1000000);

Результаты:

User time: 29.53
System time: 2.71

Пример 2 :

for($i=0;$i<10000000;$i++) {

}

// Same echo statements

Результаты:

User time: 16.69
System time: 2.1

Пример 3 :

$start = microtime(true);  
while(microtime(true) - $start < 3) {  

}  

// Same echo statements

Результаты:

User time: 34.94
System time: 3.14

Очевидно, что никакая информация не является правильной , за исключением, может быть, системного времени в третьем примере. Так что я делаю не так? Мне бы очень хотелось использовать эту информацию, но она должна быть надежной.

Я использую Ubuntu Server 8.04 LTS (32-разрядная версия), и это вывод php -v:

PHP 5.2.4-2ubuntu5.10 with Suhosin-Patch 0.9.6.2 (cli) (built: Jan  6 2010 22:01:14)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies

Ответы [ 2 ]

2 голосов
/ 28 апреля 2010

Вы можете использовать системную команду 'time' для внешней проверки этой информации:

/usr/bin/time php script.php

, который напечатает что-то вроде:

0.03user 0.00system 0:03.04elapsed 0%CPU (0avgtext+0avgdata 32752maxresident)k
0inputs+0outputs (0major+2234minor)pagefaults 0swaps

Конечно, не забывайте, что информация getrusage () - это используемое время процессора, а microtime () - время настенных часов. Программа может работать в течение 10 минут в соответствии с настенными часами, но внутренне может использовать только несколько секунд процессорного времени. Затем идет борьба за процессорное время со всеми фоновыми программами, работающими в системе, конкуренция за ресурсы, а также регулярное ведение домашнего хозяйства.

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

пользователь: 0,98, 0,09, 0,90 sys: 0,12, 0,05, 0,94

Очевидно, довольно большая разница. Даже простой <? print_r(getrusage()) ?> имеет время / интервал от 0 до 0,03.

Попробуйте запустить свои циклы в течение более длительных периодов времени, и сделайте что-нибудь в них, чтобы увеличить использование процессора. Сейчас ваши цифры слишком малы, чтобы их можно было точно измерить.

0 голосов
/ 28 апреля 2010

Благодаря совету Марка Б я смог выяснить, что смехотворно короткие времена вызывали ошибки в вычислениях getrusage().

Я создал обходной путь, чтобы отбросить эти неточные цифры. Вот код:

define('SCRIPT_START', microtime(1));

register_shutdown_function('record_activity');

/* Do work here */

function record_activity()
{
    $data = getrusage();
    $cpuu = ($data['ru_utime.tv_sec'] + $data['ru_utime.tv_usec'] / 1000000);
    $cpus = ($data['ru_stime.tv_sec'] + $data['ru_stime.tv_usec'] / 1000000);
    $renderedtime = round(microtime(1) - SCRIPT_START, 6);

    // Have some log function to put this info somewhere
    insert_record($renderedtime,
        //Only pass user CPU time if it's less than or equal to rendered time
        ($renderedtime >= $cpuu ? $cpuu : NULL ),
        //Only pass system CPU time if it's less than or equal to rendered time
        ($renderedtime >= $cpus ? $cpus : NULL ));
}

Надеюсь, это будет полезно всем, кто столкнулся с такой же проблемой.

...