call_user_funcの履歴
例
$func = 'callback'; $arg1 = 'Hello'; $arg2 = 'World'; $result = call_user_func($func, $arg1, $arg2); echo $result; function callback($arg1, $arg2){ return $arg1 . ' ' . $arg2; }
> Hello World
テスト1
コード
require_once('Benchmark/Timer.php'); $func = 'concat'; $arg1 = 'Hello'; $arg2 = 'World'; $st = new str(); $b = new Benchmark_Timer(); $b->start(); for ($i = 0; $i < 100000; $i++){ concat($arg1, $arg2); } $b->setMarker('org'); for ($i = 0; $i < 100000; $i++){ $st->$func($arg1, $arg2); } $b->setMarker('string'); for ($i = 0; $i < 100000; $i++){ call_user_func($func, $arg1, $arg2); } $b->setMarker('call_user_func'); $b->display(); function concat($arg1, $arg2){ return $arg1 . ' ' . $arg2; } class str{ function concat($arg1, $arg2){ return $arg1 . ' ' . $arg2; } }
結果
------------------------------------------------------------- marker time index ex time perct ------------------------------------------------------------- Start 1213551357.49549100 - 0.00% ------------------------------------------------------------- org 1213551358.56999200 1.074501 25.35% ------------------------------------------------------------- call_user_func 1213551360.59016900 2.020177 47.66% ------------------------------------------------------------- string 1213551361.73394500 1.143776 26.98% ------------------------------------------------------------- Stop 1213551361.73417100 0.000226 0.01% ------------------------------------------------------------- total - 4.238680 100.00% -------------------------------------------------------------
テスト2:call_user_func
コード
require_once('Benchmark/Timer.php'); $func = 'concat'; $arg1 = 'Hello'; $arg2 = 'World'; $st = new str(); $b = new Benchmark_Timer(); $b->start(); for ($i = 0; $i < 100000; $i++){ call_user_func($func, $arg1, $arg2); } $b->setMarker('call_user_func'); for ($i = 0; $i < 100000; $i++){ call_user_func(array($st, 'concat'), $arg1, $arg2); } $b->setMarker('call_user_func(obj)'); for ($i = 0; $i < 100000; $i++){ call_user_func(array($st, 'concat'), $arg1, $arg2); } $b->setMarker('call_user_func_array(obj)'); for ($i = 0; $i < 100000; $i++){ call_user_func(array('str', 'concat'), $arg1, $arg2); } $b->setMarker('call_user_func(static)'); $b->display(); function concat($arg1, $arg2){ return $arg1 . ' ' . $arg2; } class str{ function concat($arg1, $arg2){ return $arg1 . ' ' . $arg2; } }
結果
------------------------------------------------------------------------ marker time index ex time perct ------------------------------------------------------------------------ Start 1213551872.93670100 - 0.00% ------------------------------------------------------------------------ call_user_func 1213551874.89791800 1.961217 21.03% ------------------------------------------------------------------------ call_user_func(obj) 1213551877.40661200 2.508694 26.90% ------------------------------------------------------------------------ call_user_func_array(obj) 1213551879.75447900 2.347867 25.17% ------------------------------------------------------------------------ call_user_func(static) 1213551882.26413500 2.509656 26.91% ------------------------------------------------------------------------ Stop 1213551882.26432900 0.000194 0.00% ------------------------------------------------------------------------ total - 9.327628 100.00% ------------------------------------------------------------------------
考察
- 動的メソッド呼び出しは、call_user_funcを使うよりも$func()を使う方が速い。コードにそのままメソッド書くのと大して変わらない。
- クラスメソッドをstaticに呼び出す場合、staticキーワードをつけないと、1.5倍ぐらい遅くなる。
引数を可変にしたい場合はcall_user_func_arrayを使うしかないけど、そうでない場合は$func()を使う方がいい。call_user_funcと$func()の違いは、メソッドが存在しない場合、前者はWarningなのに対して、後者はFatalになる。