What is the difference between using mt_rand($min, $max)
and rand($min, $max)
about the speed?
问题:
回答1:
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
!
回答2:
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.
回答3:
PHP Manual on mt_rand()
states that it:
which will produce random numbers four times faster than what the average libc rand() provides.
回答4:
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
回答5:
Following is the difference in speed for both of them :-mt_rand($min, $max)
is four times faster as compared to rand($min, $max)
The reason is that,rand($min, $max)
uses libc random number generator while mt_rand($min, $max)
uses Mersenne Twister which is four times faster.
Hope it will solve your doubt.
Thanks.
回答6:
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.