1月
9
2007
分類:
最近更新:
2007-01-09
PHP5 的動態函數/行為調用效率測試
我先前為了測試 PHP5 的 reflection 能力,找到《Benchmarking dynamic function/method calls》為參考文章,寫了一段效率測試碼。剛好今天看到 HACGIS 也做了《各種呼叫方式的比較》。因為 HACGIS 沒測到 reflection 的部份,所以把我的效率測試碼也放上來供各位參考。
<?php class Benchmark { public $counter; public function __construct() { $this->counter = 0; } public function increase($c, $b, $a) { //echo 'counter a = ', $a, "\n"; //echo 'counter b = ', $b, "\n"; //echo 'counter c = ', $c, "\n"; $this->counter += $c; return; } } $times = 1000000; $benchmark = new Benchmark(); $unorderedParameters = array( 'b' => 1, 'a' => 100, 'c' => 13 ); // Get an instance of the ReflectionMethod class by an ojbect $funcName = 'increase'; $func = new ReflectionMethod($benchmark, $funcName); if ($parameters = $func->getParameters()) { $i = 0; foreach ($parameters as $parameter) { $k = $parameter->getName(); $orderedParameters[$i++] = $unorderedParameters[$k]; } } printf("---> Invokation arguments: \n"); var_dump($unorderedParameters); echo "Straight method call: \n"; $benchmark->counter = 0; $start = microtime(true); for ($i = 0; $i < $times; $i++) { $benchmark->increase($unorderedParameters['c'], $unorderedParameters['b'], $unorderedParameters['a']); } $end = microtime(true); $elapsed = $end - $start; echo 'result is ', $benchmark->counter, ', elapsed : ', $elapsed, ' secs', "\n"; echo "Variable method call: \n"; $benchmark->counter = 0; $start = microtime(true); for ($i = 0; $i < $times; $i++) { $benchmark->$funcName($unorderedParameters['c'], $unorderedParameters['b'], $unorderedParameters['a']); } $end = microtime(true); $elapsed = $end - $start; echo 'result is ', $benchmark->counter, ', elapsed : ', $elapsed, ' secs', "\n"; echo "invoke method call: \n"; $benchmark->counter = 0; $start = microtime(true); for ($i = 0; $i < $times; $i++) { $func->invoke($benchmark, $unorderedParameters['c'], $unorderedParameters['b'], $unorderedParameters['a']); } $end = microtime(true); $elapsed = $end - $start; echo 'result is ', $benchmark->counter, ', elapsed : ', $elapsed, ' secs', "\n"; echo "invokeArgs method call: \n"; $benchmark->counter = 0; $start = microtime(true); for ($i = 0; $i < $times; $i++) { $func->invokeArgs($benchmark, $orderedParameters); } $end = microtime(true); $elapsed = $end - $start; echo 'result is ', $benchmark->counter, ', elapsed : ', $elapsed, ' secs', "\n"; echo "call_user_func_array method call: \n"; $benchmark->counter = 0; $start = microtime(true); $m = array(&$benchmark, $funcName); for ($i = 0; $i < $times; $i++) { call_user_func_array($m, $orderedParameters); } $end = microtime(true); $elapsed = $end - $start; echo 'result is ', $benchmark->counter, ', elapsed : ', $elapsed, ' secs', "\n"; ?>
結論... reflection 這個在 Java/C# 中的高等技巧,在 PHP 這種動態語言中就顯得有些多餘了。當行為名稱及參數個數及順序已知時,傳統調用方法的效率無疑是最好的。當參數個數及順序未知時,使用 call_user_func_array()
也比 Reflection::invokeArgs()
來得好些。
相關文章
- 動態語言關於參數宣告的寫作風格
- 活用 PHP5 的 magic methods - __set(), __get() and __call()
- 什麼是 Reflection ?
- Reflection 於設計 Framework 時之安全性作用
樂多舊網址: http://blog.roodo.com/rocksaying/archives/2633503.html
樂多舊回應