アットマークでエラーを抑制したときのオーバーヘッドについて検証してみた with php5.3三項演算子

アットマークによるエラー抑制を行った時のオーバーヘッドが大きいと聞いたので検証してみた。

アットマークを使うとコードがきれいに書けたりするけど、それでオーバーヘッドが大きくなったんじゃ困るなぁ、ってことで。

今回はphp5.3から導入された、三項演算子の省略形についてテストしてみた。

この省略形、三項演算子を利用し始めたころから常々、こんなのでないかなーって待ちわびてた。だって同じ変数を二度書く、そしてそんなのがアチコチにあるのなんて耐えられない!(マクロ関数あれば・・・、ね)

<?php
define('MAX_COUNT', 10000000);
$time_start = microtime(true);
for($i=0; $i < MAX_COUNT; $i++){
$hoge = @$unk ?: true;     // <-- コイツを検証1
}
echo $test1 = (microtime(true) - $time_start)."\n";

$time_start = microtime(true);
for($i=0; $i < MAX_COUNT; $i++){
$hoge = $unk ?: true;     // <-- コイツを検証2
}
echo $test2 = (microtime(true) - $time_start)."\n";

echo $test1 / $test2;

結果


%php atmark.php
0.111232042313  // アットマークあり (100,000回)
0.0561020374298 // アットマークなし
1.98267384589 // (倍)

%php atmark.php
1.11259889603// アットマークあり (1,000,000回)
0.561910867691 // アットマークなし
1.98002736733 // (倍)

%php atmark.php
11.166533947 // アットマークあり (10,000,000回)
5.58266806602 // アットマークなし
2.00021455959 // (倍)

およそ二倍の差があることが判明。試行回数に対してきれいに比例し、アットマークのあり、なしではこちらもきれいにおよそ二倍の比率をキープした。

今回の環境ではcpuにxeon X3330(4core 2.66GHz)を利用した。他には大してアクティブなプロセスがない状況。この環境ではアットマークによるエラー抑制のコストは1回あたり0.000006秒、6マイクロ秒と見られる。正直大したことないかも。

もちろんコストがかかることを気にせず、バンバンどこの箇所にでもアットマークを打つのはよろしくないことで。

ついでに今回は比較されるべき書き方があったので、そちらの書き方ともコストを比較してみた。

今回の事の発端となったのは、undefined variable(Undefined index)がNoticeで発せられていたことである。で、isset()を利用すべきか、@を利用すべきかで悩んでみた。

define('MAX_COUNT', 10000000);
$time_start = microtime(true);
for($i=0; $i < MAX_COUNT; $i++){
$hoge = @$unk ?: true;     // <-- コイツを検証1
}
echo $test1 = (microtime(true) - $time_start)."\n";

$time_start = microtime(true);
for($i=0; $i < MAX_COUNT; $i++){
$hoge = isset($unk) ? $unk : true;     // <-- コイツを検証2
}
echo $test2 = (microtime(true) - $time_start)."\n";

echo $test1 / $test2;


%php atmark.php
11.0903561115 // アットマークあり (10,000,000回)
1.57850503922 // isset()で逃がした
7.02586044133 //(倍)の開き

なんと性能に7倍もの開きが。ちょっとびっくり。でも一回あたりのコストはかなり小さいけどね。

まとめ

  • アットマークのエラー抑制はコストがかかる
  • でもそれって6マイクロ秒とかで1つのフローのなかでは無視できる値かも
  • ただしforループとかでガシガシ使われるようなところだとまずそう
  • 個人的には$hoge = @$unk ?: @$pokemon;好き。マジカッケーッス。
  • そもそもNoticeだとデフォルトで出力されないとか、php.ini-productionとか普通の本番環境だとwarningだってdisplay_errorsで出てこないよ、とか。

コメントを残す