2014-07-08 68 views
4

在我創建的應用程序中,我需要將未知數量的參數傳遞給類的未知構造函數。 類(+命名空間)是一個字符串,它在$ class中。 參數在數組中。PHP:性能:splat運算符或反射

此應用程序將在幾個月內部署,所以我們認爲我們可以在PHP 5.6中開發它。 所以我認爲這個解決辦法是:

$instance = new $class(...$args); 

這是工作......

但我的同事不願意接受這一點,因爲CI服務器不明白這行碼。 他們的解決方案寧願:

$reflect = new \ReflectionClass($class); 
$instance = $reflect->newInstanceArgs($args) 

現在:兩者都工作正常,所以這不是問題。 但我的想法是,使用其他方式(例如PHP 5.6 splat運算符),反射速度較慢。

另外問題:是否反射一個好方法,我應該從CI服務器明白那一行的那一刻起使用splat運算符?

+1

無論哪種方式的基準。如果您發現任何重大差異,請給我們寫明信片。 – deceze

+2

未知課程?這聽起來像是一個非常糟糕的設計。 –

+0

爲什麼不使用一個變量作爲params數組? – Phantom

回答

7

絕對是爲摔跤運營商,爲什麼?它比反射方法快得多(我使用它並且實現看起來非常好)。反射也會破壞與設計有關的任何事情,例如它允許您打破封裝。

PS:是不是$instance = new $class(...$args);

+1

是的,是我的一個錯字,這是正確的代碼。 – Blaatpraat

+2

快得多不是一個很好的指標。你能發表你的發現你的基準嗎? –

7

今天我找到了時間來對它進行基準測試。
這就像我期待的(和Fleshgrinder說):摔跤運算符更快。

基準時間:
反思:11.686084032059s
啪:6.8125338554382s

差不多時間的一半......這是嚴重的......

基準(通過http://codepad.org/jqOQkaZR):

<?php 

require "autoload.php"; 

function convertStdToCollectionReflection(array $stds, $entity, $initVars) 
{ 
    $records = array(); 
    $class = $entity . '\\Entity'; 
    foreach ($stds as $record) { 
     $args = array(); 
     foreach ($initVars as $var) { 
      $args[] = $record->$var; 
     } 
     $reflect = new \ReflectionClass($class); 
     $records[] = $reflect->newInstanceArgs($args); 
    } 

    return $records; 
} 

function convertStdToCollectionSplat(array $stds, $entity, $initVars) 
{ 
    $records = array(); 
    $class = $entity . '\\Entity'; 
    foreach ($stds as $record) { 
     $args = array(); 
     foreach ($initVars as $var) { 
      $args[] = $record->$var; 
     } 
     $records[] = new $class(...$args); 
    } 

    return $records; 
} 

$dummyObject = array(); 
for ($i = 0; $i < 10; $i++) { 
    $dummyclass = new \stdClass(); 
    $dummyclass->id = $i; 
    $dummyclass->description = 'Just a number... ' . $i; 
    $dummyObject[] = $dummyclass; 
} 

print 'Start Reflection test' . PHP_EOL; 
$reflectionStart = microtime(true); 

for($i = 0; $i < 1000000; $i++) { 
    convertStdToCollectionReflection(
     $dummyObject, 
     'Xcs\Core\Record', 
     array(
      'id', 
      'description' 
     ) 
    ); 
} 

$reflectionEnd = microtime(true); 

print 'Start Splat test' . PHP_EOL; 
$splatStart = microtime(true); 

for($i = 0; $i < 1000000; $i++) { 
    convertStdToCollectionSplat(
     $dummyObject, 
     'Xcs\Core\Record', 
     array(
      'id', 
      'description' 
     ) 
    ); 
} 

$splatEnd = microtime(true); 

print PHP_EOL . 'OUTPUT:' . PHP_EOL; 
print 'Reflection: ' . ($reflectionEnd - $reflectionStart) . 's' . PHP_EOL; 
print 'Splat: ' . ($splatEnd - $splatStart) . 's' . PHP_EOL; 
+0

你可以發佈你的基準嗎?否則你的答案是無用的。 –

+1

這非常直截了當,只是在兩個實現上都做了同樣的工作。 http://codepad.org/jqOQkaZR – Blaatpraat

+0

我不是說它很難:-)。我只是說沒有產生這些結果的代碼,結果本身是無用的。 +1代碼。 –