Search code examples
crandombsdarc4random

Why is rand() much faster than arc4random()?


I'm writing a game AI which requires fast integer random number generation. This game is for Mac OS, so there are two choices rand() (the plain C) and arc4random() (BSD). I didn't find any comparison in speed for these two functions, so I wrote a small program to test:

long i;

// Record timestamp here.
srand((unsigned int)time(NULL));
for (i = 0; i < 999999999; ++i) {
    rand();
}
// Record timestamp here.
for (i = 0; i < 999999999; ++i) {
    arc4random();
}
// Record timestamp here and print all three.

I tested several times. Results are quite stable: srand() and 999999999 iterations of rand() takes around 6 s, while arc4random() takes much longer (around 30 s).

Is there any reason that arc4random() takes much longer time? Or is there any flaw in my testing. Thank you!


Solution

  • Your results are reasonable.

    The two functions are designed for different purposes and they are based on completely different class of pseudorandom number generators.

    rand() is a pseudorandom number generator (PRNG), generally implemented as a linear congruential generator (LCG), which is reasonably fast but generally it has notoriously bad statistical properties.

    arc4random() is a cryptographically secure pseudorandom number generator (CSPRNG), which is generally slower but also suitable for cryptographical use, which implies it has higher statistical quality of randomness than a PRNG. According to the documentations here, here and here:

    The function when originally implemented in OpenBSD, used the RC4 cipher to produce the output stream. OpenBSD now uses a ChaCha20 stream cipher.

    and

    RC4 has been designed by RSA Data Security, Inc. It was posted anonymously to the USENET and was confirmed to be equivalent by several sources who had access to the original cipher. Since RC4 used to be a trade secret, the cipher is now referred to as ARC4.


    It is important to understand what is the difference between the two class of pseudorandom number generators.

    A PRNG is designed for purposes where all you care about is (ideally) high amount of statistical randomness: fields where you want simulate randomness.

    A CSPRNG is designed for purposes where the latter is simply not enough, but high amount of unpredictability (even when the generator algorithm is exactly known) is also required: the field of cryptography.

    So you don't need a CSPRNG to generate numbers with high quality of statistical randomness. All you need is a high quality PRNG. rand() is nowhere to that and arc4random() is an overshoot.

    See this page for simple, modern, high quality random number generators.