アクセッサの速度を計測する in PHP
PHPで、「$obj->var」と「$obj->get_var()」にどのくらい速度差があるのかを調べてみた。
またjQueryのようにgetterとsetterを同じメソッドで行うようにしたいとき、引数があるかどうかを調べるのにfunc_num_args()を使った場合と使わない場合との速度差も測ってみた。
class Foo {
var $var;
/// ふつうのaccessor
function var0() {
return $this->var; /// getter
}
/// jQueryライクなaccessor: func_num_args() を使わない方法
function var1($arg=null) {
if ($arg === null) {
return $this->var; /// getter
}
else {
$this->var = $arg; /// setter
return $this;
}
}
/// jQueryライクなaccessor: func_num_args() を使うバージョン
function var2($arg=null) {
if (func_num_args() === 0) {
return $this->var; /// getter
}
else {
$this->var = $arg; /// setter
return $this;
}
}
}
$x = new Foo();
$x->var = 'foo';
$times = 1000000; /// 100万回
echo "-- ", $times, " times\n";
$N = $times / 10;
echo '* $x->var: ';
$t1 = microtime(true);
for ($i = 0; $i < $N; $i++) {
$x->var; $x->var; $x->var; $x->var; $x->var;
$x->var; $x->var; $x->var; $x->var; $x->var;
}
$t2 = microtime(true);
printf("%f sec\n", $t2 - $t1);
echo '* $x->var0(): ';
$t1 = microtime(true);
for ($i = 0; $i < $N; $i++) {
$x->var0(); $x->var0(); $x->var0(); $x->var0(); $x->var0();
$x->var0(); $x->var0(); $x->var0(); $x->var0(); $x->var0();
}
$t2 = microtime(true);
printf("%f sec\n", $t2 - $t1);
echo '* $x->var1(): ';
$t1 = microtime(true);
for ($i = 0; $i < $N; $i++) {
$x->var1(); $x->var1(); $x->var1(); $x->var1(); $x->var1();
$x->var1(); $x->var1(); $x->var1(); $x->var1(); $x->var1();
}
$t2 = microtime(true);
printf("%f sec\n", $t2 - $t1);
echo '* $x->var2(): ';
$t1 = microtime(true);
for ($i = 0; $i < $N; $i++) {
$x->var2(); $x->var2(); $x->var2(); $x->var2(); $x->var2();
$x->var2(); $x->var2(); $x->var2(); $x->var2(); $x->var2();
}
$t2 = microtime(true);
printf("%f sec\n", $t2 - $t1);
実行結果: (Mac OS X 10.6, Intel Core2 Duo 2GHz, PHP 5.2.11)
$ php hoge.php -- 1000000 times * $x->var: 0.106071 sec # 直アクセス * $x->var0(): 0.432793 sec # 通常のgetter * $x->var1(): 0.669569 sec # func_num_args() なし * $x->var2(): 0.853244 sec # func_num_args() あり
考察: