Bench PHP: rand() versus mt_rand() (functions de random)

Loin de moi l’idée de remettre en cause les informations officielles de la documentation PHP, mais il paraitrait qu’utiliser mt_rand() au lieu de rand() afin de générer des nombres aléatoires est 4 fois plus rapide.

http://php.net/manual/fr/function.mt-rand.php

Par défaut, PHP utilise le générateur de nombres aléatoires de libc avec la fonction rand()mt_rand() est une fonction de remplacement, pour cette dernière. Elle utilise un générateur de nombres aléatoire de caractéristique connue, le  » » Mersenne Twister qui est 4 fois plus rapide que la fonction standard libc.

Plusieurs sites abordent déjà ce thème ici ou mais les posts sont un peu vieux et ce test n’a pas été testé  avec PHP 5.2.6

Concernant le protocole, j’ai benché avec un apache 2.2.9 sous Debian 2.6.26 dans une machine virtuelle VMWare dédiée à ça.
Apache a été redémarré après chaque exécution de la page et j’ai attendu d’avoir un load qui redescendait aux alentours 0.05.
Au début j’ai utilisé la fonction memory_get_usage() pour testé la RAM utilisée par le script mais les variations sont tellement insignifiantes que j’ai recommencé sans.

Le code source de mon fichier de teste est le suivant (c’est $iMax qui définit le nombre d’itérations) :

<?php
$iStart= time();
$i= 0;
//max boucle
$iMax=100000000;
//echo microtime();
while($i<$iMax)
{
//rand();
mt_rand();
$i++;
}

$iFin= time()-$iStart;
echo $iMax.’ iterations prennent ‘.$iFin.’ secondes’;
?>

J’ai commencé avec une boucle de 100 000 et j’ai testé plusieurs fois avec 100 millions.

Nombre d’itérationsTps d’exécution avec rand()Tps d’exécution avec mt_rand()
100 0000 sec.0 sec.
1 000 0000 sec.0 sec.
10 000 0003 sec.3 sec.
100 000 00026 sec.25 sec.
100 000 00025 sec.24 sec.
100 000 00027 sec.24 sec.
100 000 00027 sec.27 sec.
100 000 00027 sec.25 sec.

Moyenne pour 100 000 000 d’itérations avec rand() : 26.4 secondes et 0.28 de load
Moyenne pour 100 000 000 d’itérations avec mt_rand() :  25 secondes  et 0.32 de load

On ne va pas tirer des conclusions hâtives mais ce qui est certain avec ma configuration, c’est que mt_ rand() est légèrement  plus rapide sur des boucles conséquentes .
Jusqu’à 10 millions, en prenant la seconde comme échelle, on ne voit aucune différence.
Au niveau du load average du serveur, l’écart est insignifiant.

Mon fichier de test est téléchargeable à cette adresse : bench_rand_vs_mtrand.zip

Quelques informations supplémentaires sur le serveur sur lequel j’ai testé.
Faites moi un retour si vous benchez sur des configurations différentes.

cat /proc/version : Linux version 2.6.26-2-686 (Debian 2.6.26-26lenny3)  (gcc version 4.1.3 20080704 (prerelease) (Debian 4.1.2-25))

cat /proc/cpuinfo :
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Core(TM) i5 CPU 760 @ 2.80GHz
stepping : 5
cpu MHz : 2808.770
cache size : 8192 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht nx rdtscp lm constant_tsc arch_perfmon pebs bts p ni ssse3 cx16 sse4_1 sse4_2 popcnt lahf_lm ida
bogomips : 5716.00
clflush size : 64
power management:

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Core(TM) i5 CPU 760 @ 2.80GHz
stepping : 5
cpu MHz : 2808.770
cache size : 8192 KB
physical id : 0
siblings : 2
core id : 1
cpu cores : 2
apicid : 1
initial apicid : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht nx rdtscp lm constant_tsc arch_perfmon pebs bts p ni ssse3 cx16 sse4_1 sse4_2 popcnt lahf_lm ida
bogomips : 5689.11
clflush size : 64
power management:

Post Comment