As noted at Random number generator only generating one random number, it's generally incorrect to create a new instance of System.Random
every time that you need another random number, since System.Random
is seeded based upon the clock and so multiple instances created in the same tick will yield identical random numbers. As such, one common practice (at least in single-threaded applications) is to create a single instance of Random
stored in a static field that is used for all random number generation.
RNGCryptoServiceProvider
, on the other hand, does not have this particular flaw... but is apparently costly to instantiate, and therefore it's again recommended to store and reuse a single instance of it.
How about Org.BouncyCastle.Security.SecureRandom
? Do I similarly need to store and reuse a single instance of it, or is it basically fine to create instances on demand every time that I need another random number?
We can again (like in related question) look at source code to draw some conclusions (SecureRandom source code for reference).
All work in constructor goes for creating pseudo-random generator:
Creating digest (hash) costs nothing (relative to other work). For example
Sha256Digest
used by default (with empty constructor) just allocates smallbyte[]
buffer. CreatingDigestRandomGenerator
itself also costs nothing (couple small buffers). Major work done is here:It uses "master" RNG to generate seed value. Master RNG on full .NET platform is
RNGCryptoServiceProvider
(which forSecureRandom
is stored in static field and initialized only once). So all work when creatingSecureRandom
goes to creating cryptographically random seed for pseudo RNG.I'd say, it's better not create new instance every time, at least for small generation (for one-two
NextInt()
calls), because if you create new instance for every single generated number - you essentially double the costs (one time to generate crypto random number for seed and one to generate your target random number). Because (as far as I know),SecureRandom
is thread safe - there is not much reason to not reuse one instance.Side note - I don't think
RNGCryptoServiceProvider
is heavy to create as your link claims. Its constructor goes like this:So when you create new instance (without providing csp) - it reuses the same
Utils.StaticProvHandle
, so it uses the same "unmanaged" instance of RNG provider. Which in turn means creating new instance and reusing the same instance have no difference in performance. Maybe in previous versions of .NET it was not like this, not sure.