2010-04-28 6 views
4

Я пытаюсь определить использование процессора для моих PHP-скриптов. Я только что нашел this article, в котором подробно описано, как найти время использования процессора и пользователя (раздел 4).PHP getrusage() возвращает неверную информацию?

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

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

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 
+0

Я также получаю много странного поведения здесь. Возможно, из-за интерфейса SAPI – Pacerier

ответ

2

Вы можете использовать команду системного 'время', чтобы проверить эту информацию извне:

/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 

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

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

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

Очевидно вполне дисперсии. Даже простой <? print_r(getrusage()) ?> имеет utime/stimes от 0 до 0.03.

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

+0

Спасибо. Я попробую это и дам вам знать. Моя проблема: все числа больше, чем это возможно. Вы говорите, что, поскольку числа настолько малы, есть ошибки, которые вызывают огромные числа? –

+0

Я чувствую, что я в зоне сумерек. Я провел этот тест: для ($ i = 0; $ i <1000000; $ i ++) { hash ('sha512', uniqid (mt_rand(), true)); } И у меня хорошие результаты. Затем я выполнил те же самые тесты, которые я опубликовал в своем вопросе, и все они вернули ожидаемые результаты - не более 35 секунд времени CPU пользователя на 3-секундном скрипте. Я не знаю, что произошло, но теперь оно работает. Спасибо за вашу помощь. –

+0

Хорошо, неважно. Он по-прежнему дает мне огромные цифры случайным образом. Проведя намного больше испытаний, похоже, что действительно короткие времена просто испортили все. Я уже проверял время выполнения каждого сценария, поэтому мое решение - проверить, больше ли время пользователя или системы, чем время выполнения. Если это так, я игнорирую это. Если нет, я использую его. Я отправлю свой код в другом ответе. –

0

Благодаря Marc B's advice, я смог выяснить, что смехотворно короткие времена вызывают ошибки в расчетах 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)); 
} 

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

+2

Hrmm, это хорошая идея, но я не знаю о методе. Вы вычисляете время процессора, основанное на времени выполнения, которое является яблоками и апельсинами, как упомянуто другими. Запись 'getrusage()' в начале скрипта и использование этого вместо этого было бы более точным. На самом деле нет никакого способа получить точное использование ЦП отдельного скрипта, работающего в большинстве веб-серверов. В итоге вы получите процессорное время, используемое родительским процессом Apache (или другим), включая время выполнения от несвязанных скриптов. Скрипты, запущенные через CLI, имеют собственную среду исполнения, и вам нужно получить более точную информацию с ними. – pospi