What is the difference between using mt_rand($min, $max)
and rand($min, $max)
about the speed?
Update
Since PHP 7.1 mt_rand
has superseded rand
completely, and rand
was made an alias for mt_rand
. The answer below focuses on the differences between the two functions for older versions, and the reasons for introducing mt_rand
.
Speed was not why mt_rand
was introduced!
The rand
function existed way before mt_rand
, but it was deeply flawed. A PRNG must get some entropy, a number from which it generates a sequence of random numbers. If you print out a list of ten numbers that were generated by rand()
like so:
for ($i=0;$i<10;++$i)
echo rand(), PHP_EOL;
The output can be used to work out what the rand
seed was, and with it, you can predict the next random numbers. There are tools out there that do this, so google a bit and test it.
There's also an issue with rand
relativily quickly showing patterns in its random numbers as demonstrated here. A problem mt_rand
seems to solve a lot better, too.
mt_rand
uses a better randomization algorithm (Mersenne Twist), which requires more random numbers to be known before the seed can be determined and is faster. This does not mean that mt_rand
is, by definition, faster than rand
is, this only means that the way the numbers are generated is faster, and appears to have no real impact on the function's performance, as other answers here have demonstrated.
Either way, have a look at the mt_srand
and the srand
docs. I'm sure they'll contain some more info
If mt_rand
's algorithm translates in an increase in performance, then that's great for you, but it's a happy coincidence. TL;TR:
mt_rand
was introduced to fix the problems that exist in rand
!
random_int()
and random_bytes()
for security purposes. –
Headrick Update (PHP 7.1):
rand()
andsrand()
have now been made aliases tomt_rand()
andmt_srand()
, respectively. This means that the output for the following functions have changes:rand()
,shuffle()
,str_shuffle()
, andarray_rand()
.
That means that since version 7.1 there is no practical difference between both of them because rand
calls mt_rand
internally.
Before PHP 7.1:
Using rand()
is not a bad practice if it not used for security purposes, I'm usually using rand()
(habit?).
If you need an enormous amount of random numbers you will need mt_rand
instead rand
. mt_rand
has a period of 219937 − 1, far better than rand
(232). Take a look to this article about graphical pattern generation using rand
and mt_rand
.
Periodicity and entropy are the only reasons for using mt_rand()
instead rand()
and not security or speed improvements.
Mathematically mt_rand
have more entropy and a greater periodicity than rand
(219937−1 vs. 232).
If you need a few random numbers and security is not a problem, rand
will do the job (get a random number to decide firing a cleanup process).
Testing speed improvements
In practice there is not much difference in speed between the two functions (maybe because PHP⇔C wrapper overhead?).
PHP test code:
<?php
for ($c = 0; $c < 3; $c++) {
$start = microtime(true);
$sum = 0.0;
for ($i = 0; $i < 100000000; $i++) {
$sum += rand();
}
printf('[rand %d] Time: %.3f s%s', $c, microtime(true) - $start, PHP_EOL);
}
for ($c = 0; $c < 3; $c++) {
$start = microtime(true);
$sum = 0.0;
for ($i = 0; $i < 100000000; $i++) {
$sum += mt_rand();
}
printf('[mt_rand %d] Time: %.3f s%s', $c, microtime(true) - $start, PHP_EOL);
}
Tests in PHP 7.0.19:
$ php timing.php
[rand 0] Time: 4.658 s
[rand 1] Time: 4.664 s
[rand 2] Time: 4.654 s
[mt_rand 0] Time: 4.267 s
[mt_rand 1] Time: 4.255 s
[mt_rand 2] Time: 4.261 s
Tests in PHP 5.4.45 (slower machine):
$ php timing.php
[rand 0] Time: 10.862 s
[rand 1] Time: 10.889 s
[rand 2] Time: 10.615 s
[mt_rand 0] Time: 10.948 s
[mt_rand 1] Time: 9.883 s
[mt_rand 2] Time: 10.190 s
Only 6-9% and not 400% as claimed.
Using for security purposes
But if your application needs a lot of entropy because security issues, you'll need a more secure way and openssl_random_pseudo_bytes()
possibly is the best solution, does its work (far better but slower? we need security over speed?) relying on openssl related issues.
Neither rand()
nor mt_rand()
are safe enough:
Caution This function does not generate cryptographically secure values, and should not be used for cryptographic purposes. If you need a cryptographically secure value, consider using
random_int()
,random_bytes()
, oropenssl_random_pseudo_bytes()
instead.
There is PHP extensions like random_compat
, but I didn't recommend using them if it not necessary.
As of PHP 7.1 there is no difference at all. rand() is now an alias for mt_rand().
See http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.rand-srand-aliases
And more details: https://wiki.php.net/rfc/rng_fixes
PHP Manual on mt_rand()
states that it:
which will produce random numbers four times faster than what the average libc rand() provides.
rand()
is standard language construct that were in PHP for very long time (probably ported from C
language). mt_rand()
is somewhat newer as far as I know. That's why mt_rand()
is called a better rand
by Manual :) –
Eponymy rand
of old, vs mt_rand
=> the ease with which the seed can be deduced from the output, for example –
Choir mt_rand
function that is said to be faster, it's the algorithm that it uses that is faster than the average libc rand
function. That does not mean that this speed difference will translate to a performance difference in PHP... It only states that the PRNG will generate the numbers faster, nothing more, nothing less –
Choir mt_rand
is faster. Which is only partly true. The better distribution and harder to guess seed is what the real difference is, things I explained, but you just don't mention that in your answer, which makes it incomplete and a possible source of misinformation (OP believes mt_rand
is there solely for speed reasons, which is totally untrue) –
Choir rand
function, which is what PHP's rand
also uses. It does not mean (however, it sort of implies it) that mt_rand
is therefore 4 times faster. It clearly isn't. It's an incomplete quote, and thus misleading information, even more than the vague quote on the docs page... –
Choir mt_rand
to be much faster for system, which goes right with statement that numbers are generated faster. It's separate matter from PHP speed and I never said that PHP runs faster with mt_rand
over rand
. –
Eponymy They appear to be equal in speed:
function timeit($times, $func) {
$t = microtime(1);
while($times--) $func();
return microtime(1) - $t;
}
echo PHP_OS, " ", phpversion(), "\n";
echo timeit(100000, function() { rand(0,1000); }), "\n";
echo timeit(100000, function() { mt_rand(0,1000); }), "\n";
Results for OSX Mavericks and VirtualBox'ed Ubuntu 11:
Darwin 5.5.19
0.038038969039917
0.033117055892944
Linux 5.3.6-13ubuntu3.10
0.031459093093872
0.031935214996338
If these measures are correct, the manual comment mentioned elsewhere should be considered wrong/obsolete.
mt_rand
is four times faster is a horrible blanket statement that is indeed very likely to be outdated. The "average" libc rand
has probably changed a hundred times since that sentence was added to the PHP docs anyway... Besides, mt_rand
wasn't added for speed reasons, it was added because of the inherent flaws in the old rand
PRNG. speed gain was never the main reason for mt_rand
, that's what everyone seems to be forgetting here. –
Choir mt_rand
, and only focusing on speed, but then, that was the OP's question. That, and the attitude of some users got me worked up over nothing... I'm with you though, OP accepted the better answer, and so I'll leave this one be –
Choir © 2022 - 2024 — McMap. All rights reserved.
rand
was made an alias. WRT contents: it's main focus is explaining whymt_rand
was introduced initially (which is still relevant). For completeness sake, I'll add an update stating thatrand
is now an alias. Other than that, the information provided is still correct IMO – Choir