par
naholyr » 15 juin 2007, 14:04
Par curiosité (c'est à peine HS, disons un peu en retard

) j'ai testé les différentes manières de récupérer un éléments de tableau au hasard :
// Entrée : tableau "simple" (non associatif)
// Sortie : un élément au hasard
function my_array_rand_value($tableau) {
return $tableau[mt_rand(1,count($tableau)-1)];
}
// Entrée : tableau quelconque
// Sortie : un élément au hasard
function my_array_rand_value_assoc($tableau) {
$values = array_values($tableau);
return $values[mt_rand(0,count($tableau)-1)];
}
// Entrée : tableau quelconque
// Sortie : un élément au hasard
function array_rand_value($tableau) {
return $tableau[array_rand($tableau)];
}
// Construction d'un tableau
$tableau = array();
$tableau_assoc = array();
for ($i=0; $i<$nbElements; $i++) {
$tableau[] = uniqid();
$tableau_assoc[uniqid()] = uniqid();
}
$bench->setMarker('Construction des tableaux de '.$nbElements.' éléments');
// Tests des 4 possibilités
for ($i=0; $i<$nbIterations; ++$i) $res = my_array_rand_value($tableau);
$bench->setMarker($nbIterations.' appels à my_array_rand_value($tableau)');
for ($i=0; $i<$nbIterations; ++$i) $res = my_array_rand_value_assoc($tableau_assoc);
$bench->setMarker($nbIterations.' appels à my_array_rand_value_assoc($tableau_assoc)');
for ($i=0; $i<$nbIterations; ++$i) $res = array_rand_value($tableau);
$bench->setMarker($nbIterations.' appels à array_rand_value($tableau)');
for ($i=0; $i<$nbIterations; ++$i) $res = array_rand_value($tableau_assoc);
$bench->setMarker($nbIterations.' appels à array_rand_value($tableau_assoc)');
Voici les résultats pour un tout petit tableau (5 éléments, 100'000 itérations) :
Pour un tableau moyen (500 éléments, 100'000 itérations) :
Pour un grand tableau (50'000 éléments, 1'000 itérations) :
Si on compare avec les valeurs par itération en fonction du nombre d'éléments, c'est édifiant :

Bien sûr il faut lire ça en ayant en tête que A et C sont sur des tableaux "simple" alors que B et D sont sur des tableaux associatifs, donc il aurait fallu comparer A/C et B/D, mais les résultats auraient été très proches étant donné que C/D est toujours très proche de 1.
Mais ce qui apparaît le plus flagrant, et qui est la donnée vraiment intéressante c'est que
$tableau[mt_rand(0,count($tableau)-1)] se calcule en un temps totalement indépendant du nombre d'éléments du tableau, et ça c'est très fort

J'ai fait le test avec un tableau de 6'900'000 éléments (je ne peux pas plus avec ma RAM) et ça donne le même temps de 2.9 us.
En conclusion :
- Sur un tableau associatif il vaut TOUJOURS mieux utiliser array_rand(), le rapport passe vite à du 1 pour 10.
- Sur un tableau "simple" l'utilisation de mt_rand()+count() devient plus rapide à partir de 15-20 éléments, et avant elle est vraiment très proche. Donc il vaut quasiment toujours utiliser mt_rand+count

le rapport passe vite à du 1 pour 5.
- Si on peut utiliser un tableau simple au lieu d'un associatif, il vaut mieux utiliser le simple.
Par curiosité (c'est à peine HS, disons un peu en retard ;)) j'ai testé les différentes manières de récupérer un éléments de tableau au hasard :[php]// Entrée : tableau "simple" (non associatif)
// Sortie : un élément au hasard
function my_array_rand_value($tableau) {
return $tableau[mt_rand(1,count($tableau)-1)];
}
// Entrée : tableau quelconque
// Sortie : un élément au hasard
function my_array_rand_value_assoc($tableau) {
$values = array_values($tableau);
return $values[mt_rand(0,count($tableau)-1)];
}
// Entrée : tableau quelconque
// Sortie : un élément au hasard
function array_rand_value($tableau) {
return $tableau[array_rand($tableau)];
}
// Construction d'un tableau
$tableau = array();
$tableau_assoc = array();
for ($i=0; $i<$nbElements; $i++) {
$tableau[] = uniqid();
$tableau_assoc[uniqid()] = uniqid();
}
$bench->setMarker('Construction des tableaux de '.$nbElements.' éléments');
// Tests des 4 possibilités
for ($i=0; $i<$nbIterations; ++$i) $res = my_array_rand_value($tableau);
$bench->setMarker($nbIterations.' appels à my_array_rand_value($tableau)');
for ($i=0; $i<$nbIterations; ++$i) $res = my_array_rand_value_assoc($tableau_assoc);
$bench->setMarker($nbIterations.' appels à my_array_rand_value_assoc($tableau_assoc)');
for ($i=0; $i<$nbIterations; ++$i) $res = array_rand_value($tableau);
$bench->setMarker($nbIterations.' appels à array_rand_value($tableau)');
for ($i=0; $i<$nbIterations; ++$i) $res = array_rand_value($tableau_assoc);
$bench->setMarker($nbIterations.' appels à array_rand_value($tableau_assoc)');[/php]
Voici les résultats pour un tout petit tableau (5 éléments, 100'000 itérations) :
[url=http://pix.nofrag.com/ad/9b/26b0a158f310719a253ec3ff562f.html][img]http://pix.nofrag.com/ad/9b/26b0a158f310719a253ec3ff562ft2.jpg[/img][/url]
Pour un tableau moyen (500 éléments, 100'000 itérations) :
[url=http://pix.nofrag.com/09/ea/6028e44bb2bba3bf9b8be8f4b2bb.html][img]http://pix.nofrag.com/09/ea/6028e44bb2bba3bf9b8be8f4b2bbt2.jpg[/img][/url]
Pour un grand tableau (50'000 éléments, 1'000 itérations) :
[url=http://pix.nofrag.com/e2/bb/0ad365c7cbe19fbe6b5185e9a91f.html][img]http://pix.nofrag.com/e2/bb/0ad365c7cbe19fbe6b5185e9a91ft2.jpg[/img][/url]
Si on compare avec les valeurs par itération en fonction du nombre d'éléments, c'est édifiant :
[url=http://pix.nofrag.com/15/40/fe7619acb2f502560fc733118883.html][img]http://pix.nofrag.com/15/40/fe7619acb2f502560fc733118883t2.jpg[/img][/url]
Bien sûr il faut lire ça en ayant en tête que A et C sont sur des tableaux "simple" alors que B et D sont sur des tableaux associatifs, donc il aurait fallu comparer A/C et B/D, mais les résultats auraient été très proches étant donné que C/D est toujours très proche de 1.
Mais ce qui apparaît le plus flagrant, et qui est la donnée vraiment intéressante c'est que [b]$tableau[mt_rand(0,count($tableau)-1)][/b] se calcule en un temps totalement indépendant du nombre d'éléments du tableau, et ça c'est très fort ;) J'ai fait le test avec un tableau de 6'900'000 éléments (je ne peux pas plus avec ma RAM) et ça donne le même temps de 2.9 us.
En conclusion :
- Sur un tableau associatif il vaut TOUJOURS mieux utiliser array_rand(), le rapport passe vite à du 1 pour 10.
- Sur un tableau "simple" l'utilisation de mt_rand()+count() devient plus rapide à partir de 15-20 éléments, et avant elle est vraiment très proche. Donc il vaut quasiment toujours utiliser mt_rand+count ;) le rapport passe vite à du 1 pour 5.
- Si on peut utiliser un tableau simple au lieu d'un associatif, il vaut mieux utiliser le simple.