Eh bien, pour un infiniment petit tableau, $array === (array) $array
est nettement plus rapide que is_array($array)
. Sur l'ordre de plus de 7 fois plus rapide. Mais chaque appel est seulement de l'ordre de 1.0 x 10 ^ -6
secondes (0.000001 seconds
). Donc, à moins que vous appelez ça des milliers de fois, il ne va pas être la peine. Et si vous appelez ça des milliers de fois, je suggérerais que vous êtes en train de faire quelque chose de mal...
La différence vient quand vous avez affaire avec un grand tableau. Depuis $array === (array) $array
nécessite une nouvelle variable à être copié exige le tableau à parcourir en interne pour la comparaison, il sera probablement beaucoup plus lent pour un grand tableau. Par exemple, sur un tableau de 100 éléments entiers, is_array($array)
est à l'intérieur d'une marge d'erreur (< 2%
) de l' is_array()
avec un petit tableau (en 0.0909
secondes pour 10 000 itérations). Mais $array = (array) $array
est extrêmement lent. Pour seulement 100 éléments, c'est déjà plus de deux fois plus lent qu' is_array()
(en 0.203
secondes). Pour les éléments de 1000, is_array
est restée la même, mais le casting de comparaison a augmenté de 2.0699
secondes...
La raison c'est plus rapide pour les petites matrices est qu' is_array()
a la surcharge d'être un appel de fonction, où l'opération de cast est une simple construction du langage... Et de parcourir un petit variable (dans le code C) sera généralement moins cher que l'appel de la fonction de surcharge. Mais, pour les grandes variables, l'écart grandit...
C'est un compromis. Si le tableau est assez petit, l'itération sera plus efficace. Mais comme la taille de la matrice augmente, il devient de plus en plus lent (et donc l'appel de la fonction devient plus rapide).
Une Autre Façon De Voir Les Choses
Une autre façon de voir les choses serait d'examiner la complexité algorithmique de chaque fonte.
Jetons un coup d'oeil à l' is_array()
première. C'est le code source montre fondamentalement c'est un O(1)
de l'opération. C'est une constante de temps de l'opération. Mais nous avons aussi besoin de regarder à l'appel de la fonction. En PHP, les appels de fonction avec un seul paramètre de type tableau sont soit O(1)
ou O(n)
selon si la copie sur écriture doit être déclenchée. Si vous appelez is_array($array)
lorsque $array
est une variable de référence, de copie sur écriture sera déclenchée et une copie de la variable qui va se produire.
Donc, par conséquent, is_array()
est un meilleur des cas O(1)
et le pire-cas O(n)
. Mais tant que vous n'êtes pas à l'aide de références, c'est toujours O(1)
...
Le casting de la version, d'autre part, n'deux opérations. Il fait un jeté, puis il effectue un contrôle d'égalité. Jetons un oeil à chacune d'elles séparément. L'opérateur de cast gestionnaire oblige dans un premier temps une copie de la variable d'entrée. Peu importe si c'est une référence ou pas. Donc tout simplement à l'aide de l' (array)
opérateur de coulée forces de l' O(n)
itération sur le tableau de le jeter (via le copy_ctor appel).
Ensuite, il convertit la nouvelle copie d'un tableau. C'est - O(1)
pour les tableaux et les primitives, mais O(n)
pour les objets.
Puis, à l'identique de l'opérateur exécute. Le gestionnaire est juste un proxy à l' is_identical_function()
. Maintenant, is_identical court-circuit si $array
n'est pas un tableau. Par conséquent, il a un meilleur des cas, d' O(1)
. Mais si $array
est un tableau, il peut court-circuit à nouveau si les tables de hachage sont identiques (ce qui signifie les deux variables sont de copie sur écriture des copies les uns des autres). Donc, ce cas est - O(1)
ainsi. Mais n'oubliez pas que nous avons forcé un exemplaire ci-dessus, nous ne pouvons pas le faire si c'est un tableau. Il est donc O(n)
grâce à zend_hash_compare...
De sorte que le résultat final est ce tableau de pire cas d'exécution:
+----------+-------+-----------+-----------+---------------+
| | array | array+ref | non-array | non-array+ref |
+----------+-------+-----------+-----------+---------------+
| is_array | O(1) | O(n) | O(1) | O(n) |
+----------+-------+-----------+-----------+---------------+
| (array) | O(n) | O(n) | O(n) | O(n) |
+----------+-------+-----------+-----------+---------------+
Notez qu'il ressemble à plus grande échelle le même pour les références. Ils n'en ont pas. Ils ont tous deux l'échelle linéaire pour les variables référencées. Mais le facteur constant changement. Par exemple, dans un référencés tableau de taille 5, is_array effectuera 5 allocations de mémoire, et 5 de la mémoire des copies, suivi par 1 vérification de type. Le casting de la version, d'autre part, effectuera 5 allocations de mémoire, 5 mémoire des copies, suivi par 2 type de contrôles, suivi de 5 type de contrôles et 5 contrôles d'égalité (memcmp()
ou similaire). Donc, n=5
rendements 11 ops is_array
, encore 22 ops ===(array)
...
Maintenant, is_array()
ne O(1) les frais généraux d'une pile push (en raison de l'appel de la fonction), mais qui ne feront qu'dominer runtime pour de très petites valeurs de n
(nous l'avons vu dans la référence ci-dessus à seulement 10 éléments d'un tableau a été suffisant pour éliminer complètement toute la différence).
La Ligne De Fond
Je vous conseille d'aller pour des raisons de lisibilité si. - Je trouver de l' is_array($array)
à être beaucoup plus lisible qu' $array === (array) $array
. Ainsi, vous obtenez le meilleur des deux mondes.
Le script que j'ai utilisé pour le test:
$elements = 1000;
$iterations = 10000;
$array = array();
for ($i = 0; $i < $elements; $i++) $array[] = $i;
$s = microtime(true);
for ($i = 0; $i < $iterations; $i++) is_array($array);
$e = microtime(true);
echo "is_array completed in " . ($e - $s) ." Seconds\n";
$s = microtime(true);
for ($i = 0; $i < $iterations; $i++) $array === (array) $array;
$e = microtime(true);
echo "Cast completed in " . ($e - $s) ." Seconds\n";
Edit: Pour l'enregistrement, ces résultats ont été avec 5.3.2 sur Linux...
Edit2: Fixe la raison pour laquelle le tableau est plus lent (c'est en raison de l'itération en comparaison à la place de la mémoire raisons). Voir compare_function pour l'itération code...