srand#
Seed the pseudo-random number generator.
srand sets the internal state of the PRNG that rand draws
from. Call it with an explicit integer to get a reproducible stream,
or call it with no argument to reseed from the best entropy source
the platform offers. Since Perl 5.14 srand returns the seed it
used, so you can log it and replay the same run later.
Synopsis#
srand EXPR
srand
What you get back#
The seed that was installed, as an integer. For srand($n) the return
value is $n (after the usual integer truncation). For argument-less
srand() the return value is the auto-chosen seed drawn from system
entropy — capture it if you ever want to reproduce the run.
my $seed = srand(); # auto-seed, remember what we used
warn "seed for this run: $seed\n";
Before Perl 5.14 srand returned nothing useful. Code that relies on
the seed return should declare the minimum version:
use v5.14; # so srand returns the seed
Global state#
srand mutates a single process-wide PRNG. Every subsequent call to
rand in the same process — from any package, any module, any
thread-free context — reads from that one state. There is no
per-package or per-scope RNG. Consequences:
Calling
srand($k)anywhere in the program affects every laterrandcall, including those inside modules you did not write.Two processes that call
srand($k)with the same$kproduce identicalrandstreams. This is the basis of reproducible tests and the reason you must reseed afterfork.If
srandis never called explicitly, it is called implicitly without argument the first timerandis invoked.
Examples#
Reproducible test case with an explicit seed — same input, same sequence, every run:
srand(42);
my @sample = map { rand() } 1..5; # identical on every invocation
Seed from time() for rare-collision randomness across separate runs
started at different wall-clock seconds. This is the classical
pattern; it is not cryptographic-grade:
srand(time() ^ $$); # time XOR pid, old-school spread
Save-seed, restore-seed pattern for a test that picks a random subset of its cases but logs enough to replay any failure:
my $seed = srand(); # auto-seed, capture it
eval { run_randomised_tests() };
if ($@) {
warn "FAILED with seed=$seed — reproduce with: srand($seed)\n";
die $@;
}
Reseed after fork so parent and child do not share a stream:
my $pid = fork();
die "fork: $!" unless defined $pid;
if ($pid == 0) {
srand(); # child gets fresh entropy
exec_child_work();
}
Two independent streams from the same seed — useful when you want to checkpoint and resume, or diff two runs that diverged after a decision point:
srand(12345);
my @first = map { rand() } 1..10;
srand(12345);
my @second = map { rand() } 1..10; # identical to @first
Edge cases#
No-argument form auto-seeds with the best available entropy. On Linux this draws from
/dev/urandom(orgetrandom(2)). The seed is wide enough that you should treat it as opaque, not as a small integer.Do not call
srand()without arguments more than once per process. The PRNG’s internal state already carries more entropy than any single seed can restore, so re-seeding loses randomness rather than adding it. The two legitimate reasons to call it repeatedly are (a) with an explicit seed for reproducibility, and (b) once in each child afterfork.Decimal arguments are silently truncated to integer.
srand(42)andsrand(42.9)install the same seed. Always pass an integer so intent is obvious.Same seed ⇒ identical
randstream. That is the whole point for tests; it is the whole problem for security.Not cryptographically secure.
rand/sranduse a fast non-cryptographic PRNG. Do not use them to generate session tokens, nonces, keys, password salts, or anything an adversary must not be able to predict. UseCrypt::URandomor read from/dev/urandomdirectly.PERL_RAND_SEEDenvironment variable. If set to a non-negative integer at process startup, argument-lesssrand()(including the implicit call triggered by the firstrand) installs a deterministic seed derived from that value. The derivation is deliberately unspecified; only same-value-same-binary-same-code reproducibility is guaranteed. Intended for debugging and performance analysis. The variable is read once at startup; mutating%ENVlater has no effect on the current process.Threads (
use threads): each interpreter clone gets its own PRNG state. Seeding in one thread does not affect another.Scope of the seed: there is no way to
local-ise the PRNG state. If a library you call in between does ansrand, your stream is perturbed. Capture and restore manually if that matters.
Differences from upstream#
Fully compatible with upstream Perl 5.42. PERL_RAND_SEED is
honoured with the same “deliberately unspecified but reproducible”
contract as perl5.
See also#
rand— the consumer of the statesrandinstalls; draws the next value from the seeded streamtime— seconds since the epoch; the classic quick-and-dirty seed source for non-security code (srand(time() ^ $$))Crypt::URandom— cryptographically secure random bytes from the OS entropy pool; use this, notrand, for tokens and keysMath::Random::MT— Mersenne Twister PRNG with its own independent state, when you need a second stream that is not perturbed by library calls torandperlrun— documents thePERL_RAND_SEEDenvironment variable and other startup knobs