Difference between mt_rand() and rand()
Asked Answered
H

5

48

What is the difference between using mt_rand($min, $max) and rand($min, $max) about the speed?

Helpmeet answered 27/2, 2015 at 8:37 Comment(0)
C
78

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!

Choir answered 27/2, 2015 at 8:52 Comment(2)
@PEMapModder The answer was written ~2 years ago, before rand was made an alias. WRT contents: it's main focus is explaining why mt_rand was introduced initially (which is still relevant). For completeness sake, I'll add an update stating that rand is now an alias. Other than that, the information provided is still correct IMOChoir
Note that mt_rand() is flawed as well, the seed can be recovered with untwister, and can be used to calculate future (and past) values. In PHP 7, use random_int() and random_bytes() for security purposes.Headrick
C
34

Update (PHP 7.1):

rand() and srand() have now been made aliases to mt_rand() and mt_srand(), respectively. This means that the output for the following functions have changes: rand(), shuffle(), str_shuffle(), and array_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(), or openssl_random_pseudo_bytes() instead.

There is PHP extensions like random_compat, but I didn't recommend using them if it not necessary.

Calamity answered 27/2, 2015 at 8:54 Comment(2)
I think this answer would be better if the updates (PHP 7.1) are put at the beginning of the answer.Amylopectin
Thanks for the suggestion! I'll edit the answer at home.Calamity
P
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

Physiological answered 14/12, 2016 at 5:46 Comment(0)
E
2

PHP Manual on mt_rand() states that it:

which will produce random numbers four times faster than what the average libc rand() provides.

Eponymy answered 27/2, 2015 at 8:40 Comment(11)
So why rand() exists?Helpmeet
@Marveylabs 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
@Forien: You're forgetting the problems with rand of old, vs mt_rand => the ease with which the seed can be deduced from the output, for exampleChoir
@Forien: Please check the docs again, it's not the 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 lessChoir
@EliasVanOotegem yes, that means "faster" for system, not PHP. But if you don't see difference in PHP speed, but have better distribution and put less strain on system on the server, why don't use it?Eponymy
@Forien: You should use it, of course. But the title of this question is "What's the difference", to which you say 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
@Forien: so, why exactly did you remove my edit? Do you still believe this quote to be true? Please read other answers.Hemielytron
@georg: The quote is probably true, but it's incomplete. What the quote states is that the Mersenne twist algo is four times faster than the PRNG algo in the "average" libc 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
@Hemielytron Wherever my answer is true or false, I do not allow anyone, to post their words under my name. Plus, @Calamity posted timings which shows 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
@Forien: Strange, the answer by OscarGarcia looks to me to say, and I'm quoting here, "there is not much difference between the two functions". Also: any answer you post here falls under a creative commons license, so edits are allowed, whether you like it or notChoir
Note that this answer is obsolete. See https://mcmap.net/q/275379/-difference-between-mt_rand-and-rand for PHP 7.1 onward.Amylopectin
H
-1

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.

Hemielytron answered 27/2, 2015 at 8:47 Comment(3)
The claim that 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
@EliasVanOotegem: actually, the whole debate appears to be much ado about nothing to me. For "weak" randomness ("shuffle cards") it doesn't matter if you use rand or mt_ and in serious applications (cryptography) you should use neither.Hemielytron
You're right. It's a bit of a pointless debate. I just got carried away by the answers all failing to mention the better distribution of 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 beChoir

© 2022 - 2024 — McMap. All rights reserved.