108 votes

Qu'est-ce qui est le plus rapide : in_array ou isset ?

Cette question ne concerne que moi, car j'aime toujours écrire un code optimisé qui peut fonctionner même sur des serveurs lents et bon marché (ou des serveurs avec BEAUCOUP de trafic).

J'ai regardé autour de moi et je n'ai pas pu trouver de réponse. Je me demandais ce qui est plus rapide entre ces deux exemples en gardant à l'esprit que les clés du tableau dans mon cas ne sont pas importantes (pseudo-code naturellement) :

<?php
$a = array();
while($new_val = 'get over 100k email addresses already lowercased'){
    if(!in_array($new_val, $a){
        $a[] = $new_val;
        //do other stuff
    }
}
?>

<?php
$a = array();
while($new_val = 'get over 100k email addresses already lowercased'){
    if(!isset($a[$new_val]){
        $a[$new_val] = true;
        //do other stuff
    }
}
?>

Comme le sujet de la question n'est pas la collision de tableaux, je voudrais ajouter que si vous avez peur de la collision d'insertions pour $a[$new_value] vous pouvez utiliser $a[md5($new_value)] . cela peut encore provoquer des collisions, mais cela empêcherait une éventuelle attaque DoS lors de la lecture d'un fichier fourni par l'utilisateur ( http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html )

133voto

David Harkness Points 16674

Les réponses jusqu'ici sont justes. Utilisation de isset dans ce cas, est plus rapide car

  • Il utilise une recherche de hachage O(1) sur la clé alors que in_array doit vérifier chaque valeur jusqu'à ce qu'il trouve une correspondance.
  • Etant un opcode, il a moins de frais que l'appel à la fonction in_array fonction intégrée.

On peut les démontrer en utilisant un tableau avec des valeurs (10 000 dans le test ci-dessous), en forçant in_array pour faire plus de recherches.

isset:    0.009623
in_array: 1.738441

Il s'appuie sur le benchmark de Jason en remplissant des valeurs aléatoires et en trouvant occasionnellement une valeur qui existe dans le tableau. Tout est aléatoire, donc attention aux fluctuations des temps.

$a = array();
for ($i = 0; $i < 10000; ++$i) {
    $v = rand(1, 1000000);
    $a[$v] = $v;
}
echo "Size: ", count($a), PHP_EOL;

$start = microtime( true );

for ($i = 0; $i < 10000; ++$i) {
    isset($a[rand(1, 1000000)]);
}

$total_time = microtime( true ) - $start;
echo "Total time: ", number_format($total_time, 6), PHP_EOL;

$start = microtime( true );

for ($i = 0; $i < 10000; ++$i) {
    in_array(rand(1, 1000000), $a);
}

$total_time = microtime( true ) - $start;
echo "Total time: ", number_format($total_time, 6), PHP_EOL;

49voto

Jason McCreary Points 35919

Ce qui est plus rapide : isset() vs in_array()

isset() est plus rapide.

Alors que ça devrait être évident, isset() ne teste qu'une seule valeur. Alors que in_array() va itérer sur le tableau entier, en testant la valeur de chaque élément.

L'analyse comparative grossière est assez facile à réaliser en utilisant microtime() .

Résultats :

Total time isset():    0.002857
Total time in_array(): 0.017103

Note : Les résultats étaient similaires, qu'ils existent ou non.

Code :

<?php
$a = array();
$start = microtime( true );

for ($i = 0; $i < 10000; ++$i) {
    isset($a['key']);
}

$total_time = microtime( true ) - $start;
echo "Total time: ", number_format($total_time, 6), PHP_EOL;

$start = microtime( true );

for ($i = 0; $i < 10000; ++$i) {
    in_array('key', $a);
}

$total_time = microtime( true ) - $start;
echo "Total time: ", number_format($total_time, 6), PHP_EOL;

exit;

Ressources supplémentaires

Je vous encourage également à regarder :

19voto

Jack Points 88446

Utilisation de isset() bénéficie d'une recherche plus rapide parce qu'elle utilise un fichier table de hachage évitant ainsi la nécessité de O(n) recherches.

La clé est d'abord hachée en utilisant la méthode fonction de hachage djb pour déterminer le godet de clés hachées de manière similaire dans O(1) . Le seau est ensuite recherché de manière itérative jusqu'à ce que la clé exacte soit trouvée dans O(n) .

En l'absence de toute collisions de hachage intentionnelles cette approche donne de bien meilleures performances que in_array() .

Notez que lorsque vous utilisez isset() de la manière que vous avez montrée, le passage des valeurs finales à une autre fonction nécessite l'utilisation de la fonction array_keys() pour créer un nouveau tableau. Un compromis de mémoire peut être fait en stockant les données à la fois dans les clés et les valeurs.

Mise à jour

Un bon moyen de voir comment vos décisions en matière de conception de code affectent les performances d'exécution, vous pouvez consulter l'outil version compilée de votre script :

echo isset($arr[123])

compiled vars:  !0 = $arr
line     # *  op                           fetch      ext  return  operands
-----------------------------------------------------------------------------
   1     0  >   ZEND_ISSET_ISEMPTY_DIM_OBJ              2000000  ~0      !0, 123
         1      ECHO                                                 ~0
         2    > RETURN                                               null

_echo in_array(123, $arr)_

compiled vars:  !0 = $arr
line     # *  op                           fetch      ext  return  operands
-----------------------------------------------------------------------------
   1     0  >   SEND_VAL                                             123
         1      SEND_VAR                                             !0
         2      DO_FCALL                                 2  $0      'in_array'
         3      ECHO                                                 $0
         4    > RETURN                                               null

Non seulement in_array() utiliser une méthode relativement inefficace O(n) il doit également être appelé en tant que fonction ( DO_FCALL ) alors que isset() utilise un seul opcode ( ZEND_ISSET_ISEMPTY_DIM_OBJ ) pour cela.

8voto

Mike Brant Points 39322

La seconde serait plus rapide, car elle ne recherche que la clé spécifique du tableau et n'a pas besoin d'itérer sur l'ensemble du tableau jusqu'à ce qu'elle soit trouvée (elle examinera chaque élément du tableau si elle n'est pas trouvée).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X