php getRusage()誤った情報を返しますか?
-
02-10-2019 - |
質問
PHPスクリプトのCPU使用を決定しようとしています。見つけたばかりです この記事 これについては、システムとユーザーのCPU使用時間を見つける方法について説明します(セクション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
明らかに、情報はどれも正しいものではありません 3番目の例のシステム時間を除く。それで、私は何が間違っているのですか?私は本当にこの情報を使用できるようにしたいのですが、信頼できる必要があります。
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
解決
システム「時間」コマンドを使用して、この情報を外部的に確認できます。
/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()情報が使用されているCPU時間であり、microTime()がウォールクロック時間であることを忘れないでください。プログラムは、壁の時計に応じて10分間実行される場合がありますが、内部的にはCPU時間の数秒しか使用できません。次に、システムで実行されているすべてのバックグラウンドプログラム、リソースの競合、および定期的なハウスキーピングでCPU時間の競合があります。
このような短い期間、正確なタイミングを取得できるようにするには、あまりにも多くの要因が必要です。の3回の実行を行います while(microtime())
あなたのループのバージョン、私は次のタイミングを得ました:
ユーザー:0.98、0.09、0.90 SYS:0.12、0.05、0.94
明らかにかなりのばらつき。単純なだけです <? print_r(getrusage()) ?>
0から0.03の範囲のUtime/Stimesがあります。
ループをより長い期間実行してみてください。CPU使用量を増やすために、その中で何かをしてください。現在、あなたの数は小さすぎて正確に測定できません。
他のヒント
ありがとう マークBのアドバイス, 、私は途方もなく短い時間がエラーを引き起こしていることを理解することができました 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 ));
}
うまくいけば、これが同じ問題を経験している他の人に役立つでしょう。