2014-07-08 3 views
4

Dans une application que je crée, j'ai besoin de passer un nombre inconnu de paramètres à un constructeur inconnu d'une classe. La classe (+ namespace) est une chaîne, c'est-à-dire dans $ class. Les paramètres sont dans un tableau.PHP: Performance: opérateur splat ou réflexion

Cette application sera déployée sur quelques mois, nous avons donc pensé pouvoir la développer en PHP 5.6. Je pensais que la solution serait:

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

Cela fonctionne ...

Mais mes collègues ne veulent pas accepter cela, parce que le serveur CI ne comprend pas cette ligne de code. Leur solution serait plutôt:

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

maintenant: les deux fonctionnent très bien, de sorte que ce n'est pas le problème. Mais ma pensée est que la réflexion est plus lente, puis en utilisant d'autres moyens (comme l'opérateur splat PHP 5.6).

Egalement la question: est-ce que la réflexion est un bon moyen, dois-je utiliser l'opérateur splat à partir du moment où le serveur CI comprend cette ligne?

+1

Benchmark dans les deux cas. Écrivez-nous une carte postale si vous trouvez une différence significative. – deceze

+2

classe inconnue? cela ressemble à un très mauvais design. –

+0

Pourquoi ne pas utiliser une variable comme tableau de params? – Phantom

Répondre

7

Décidément aller pour l'opérateur Splat, pourquoi? C'est beaucoup plus rapide que l'approche par réflexion (je l'utilise et la mise en œuvre semble très bonne). La réflexion brise aussi tout ce qui a trait au design, elle permet par exemple de casser l'encapsulation.

PS: N'est-ce pas $instance = new $class(...$args);?

+1

Oui, était une faute de frappe de mon côté, c'est le code correct. – Blaatpraat

+2

Beaucoup plus rapide n'est pas vraiment une bonne mesure. Pouvez-vous poster votre référence avec votre conclusion. –

7

Aujourd'hui, j'ai trouvé le temps de le comparer.
Et c'est comme si je m'y attendais (et Fleshgrinder a dit): l'opérateur splat est plus rapide.

fois Benchmark:
Réflexion: 11.686084032059s
Splat: 6.8125338554382s

Près de la moitié du temps ... C'est sérieux ...

Benchmark (via 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

Pouvez-vous publier votre indice de référence. Sinon, votre réponse est inutile. –

+1

C'est assez simple, juste faire le même travail avec les deux implémentations. http://codepad.org/jqOQkaZR – Blaatpraat

+0

Je ne disais pas que c'est dur :-). Je viens de dire que sans code qui a produit ces résultats, les résultats par eux-mêmes sont inutiles. +1 pour le code. –