//constructor public Rand() { int length = (int)(rand.NextDouble() * 2.0d + 1.0d); for (int i = 0; i < length; i++) { generator.AddSeedMaterial(seed.GenerateSeed(128, false)); } }
private static void MainThreadLoop() { try { // ThreadedSeedGenerator performs better with large hunks of data, but if we just use MaxPoolSize, then the whole // thing gets drained before it starts refilling. In effect, the pool will drain by one unit of byteCount, before it // starts refilling, and likewise, there will be zero bytes available until at least one unit of byteCount becomes // available. So there's a balancing act happening here... Faster throughput versus faster response time... // Divide by 8 seems to be a reasonable compromise between the two. var byteCount = MaxPoolSize / 8; while (true) { // The only time we ever quit is on the terminate signal ... interrupt signal ... whatever. OS kills my thread. if (SafeStream.Length < MaxPoolSize) { var newBytes = new byte[byteCount]; // By my measurements, estimated entropy returned by ThreadedSeedGenerator is approx 0.6 or 0.7 bits per bit // when fast=false, and 0.5 when fast=true. Occasionally we see measurements between 0.4 and 0.5. So round this // down to 0.125, and just generate 8x as much data as you need. And mix it. for (var i = 0; i < 8; i++) { var maskBytes = MyThreadedSeedGenerator.GenerateSeed(byteCount, true); for (var j = 0; j < newBytes.Length; j++) { newBytes[j] ^= maskBytes[j]; } Array.Clear(maskBytes, 0, maskBytes.Length); } SafeStream.Write(newBytes, 0, newBytes.Length); } else { PoolFullAre.WaitOne(); } } } catch { // TODO think about changing architecture so we correctly avoid disposing static objects, and we gracefully terminate, etc // It is not good to catch and swallow all exceptions. // // If we got disposed while in the middle of doing stuff, we could throw any type of exception, and // I would want to suppress those. } }
private void MainThreadLoop() { try { // ThreadedSeedGenerator performs better with large hunks of data, but if we just use MaxPoolSize, then the whole // thing gets drained before it starts refilling. In effect, the pool will drain by one unit of byteCount, before it // starts refilling, and likewise, there will be zero bytes available until at least one unit of byteCount becomes // available. So there's a balancing act happening here... Faster throughput versus faster response time... // Divide by 8 seems to be a reasonable compromise between the two. var byteCount = MaxPoolSize / 8; while (true) { if (_bytes.Length >= MaxPoolSize) { _poolFullAre.WaitOne(); continue; // The only time we ever quit is on the terminate signal ... interrupt signal ... whatever. OS kills the thread. } var newBytes = new byte[byteCount]; // By my measurements, estimated entropy returned by ThreadedSeedGenerator is approx 0.6 or 0.7 bits per bit // when fast=false, and 0.5 when fast=true. Occasionally we see measurements between 0.4 and 0.5. So round this // down to 0.125, and just generate 8x as much data as you need. And mix it. for (var i = 0; i < 8; i++) { var maskBytes = _threadedSeedGenerator.GenerateSeed(byteCount, true); for (var j = 0; j < newBytes.Length; j++) { newBytes[j] ^= maskBytes[j]; } Array.Clear(maskBytes, 0, maskBytes.Length); } _bytes.Write(newBytes, 0, newBytes.Length); } } catch { if (!IsDisposed()) { throw; } // Swallow any exceptions if we get disposed in the middle of doing stuff // TODO: Gracefully terminate instead. } }
public static void Main(string[] args) { /* * It's always good to call StartEarly.StartFillingEntropyPools() as early as possible when the application is launched. * But during benchmarking performance below, then it's not really fair to let them start early. */ Benchmark("SystemRng", bytesBuffer => { var mySystemRngCryptoServiceProvider = new SystemRng(); mySystemRngCryptoServiceProvider.GetBytes(bytesBuffer); return(bytesBuffer); }); Benchmark("RNGCryptoServiceProvider", bytesBuffer => { using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(bytesBuffer); } return(bytesBuffer); }); /* * Test each of the ThreadedSeedGeneratorRng and ThreadSchedulerRng prior to doing SafeRandom * or FastRandom, because otherwise, SafeRandom will create static instances of them, which race, etc * thus throwing off my results. */ Benchmark("ThreadedSeedGeneratorRng", bytesBuffer => { var myThreadedSeedGeneratorRng = new ThreadedSeedGeneratorRng(); myThreadedSeedGeneratorRng.GetBytes(bytesBuffer); return(bytesBuffer); }); SleepForPools(3000); Benchmark("ThreadedSeedGenerator(fast)", bytesBuffer => { var myThreadedSeedGenerator = new ThreadedSeedGenerator(); var seed = myThreadedSeedGenerator.GenerateSeed(RandBytesLength, true); return(seed); }); Benchmark("ThreadedSeedGenerator(slow)", bytesBuffer => { var myThreadedSeedGenerator = new ThreadedSeedGenerator(); var seed = myThreadedSeedGenerator.GenerateSeed(RandBytesLength, false); return(seed); }); Benchmark("ThreadSchedulerRNG(slow)", bytesBuffer => { var threadSchedulerRng = new ThreadSchedulerRng(); threadSchedulerRng.GetBytes(bytesBuffer); return(bytesBuffer); }); SleepForPools(15000); Benchmark( "SafeRandom", bytesBuffer => SafeRandom.StaticInstance.GetBytes(bytesBuffer.Length)); SleepForPools(15000); Benchmark( "FastRandom", bytesBuffer => FastRandom.StaticInstance.GetBytes(bytesBuffer.Length)); SleepForPools(15000); Console.WriteLine(""); PresentResults(); Console.WriteLine(""); Console.Error.WriteLine("Finished"); Console.Out.Flush(); Console.ReadKey(); }
protected static int RandomInt(int max) { var randomBytes = Random.GenerateSeed(4, false); return(Math.Abs((int)BitConverter.ToUInt32(randomBytes, 0) % max)); }
public static void Main(string[] args) { // It's always good to StartFillingEntropyPools as early as possible when the application is launched. // But if I'm benchmarking performance below, then it's not really fair to let them start early. // StartEarly.StartFillingEntropyPools(); DateTime before; DateTime after; RandomResult result; const int randBytesLength = 8 * 1024; var results = new List <RandomResult>(); //AllZeros result = new RandomResult { AlgorithmName = "AllZeros" }; before = DateTime.Now; var randBytes = new byte[randBytesLength]; after = DateTime.Now; result.TimeSpan = after - before; result.CompressionRatio = CompressionUtility.GetCompressionRatio(randBytes).Result; results.Add(result); //SystemRng result = new RandomResult { AlgorithmName = "SystemRng" }; Console.Write(result.AlgorithmName + " "); before = DateTime.Now; var mySystemRngCryptoServiceProvider = new SystemRng(); mySystemRngCryptoServiceProvider.GetBytes(randBytes); after = DateTime.Now; result.TimeSpan = after - before; result.CompressionRatio = CompressionUtility.GetCompressionRatio(randBytes).Result; results.Add(result); Console.WriteLine((after - before).ToString()); //RNGCryptoServiceProvider result = new RandomResult(); result.AlgorithmName = "RNGCryptoServiceProvider"; Console.Write(result.AlgorithmName + " "); before = DateTime.Now; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(randBytes); } after = DateTime.Now; result.TimeSpan = after - before; result.CompressionRatio = CompressionUtility.GetCompressionRatio(randBytes).Result; results.Add(result); Console.WriteLine((after - before).ToString()); //ThreadedSeedGeneratorRng result = new RandomResult(); result.AlgorithmName = "ThreadedSeedGeneratorRng"; Console.Write(result.AlgorithmName + " "); before = DateTime.Now; var myThreadedSeedGeneratorRng = new ThreadedSeedGeneratorRng(); myThreadedSeedGeneratorRng.GetBytes(randBytes); after = DateTime.Now; result.TimeSpan = after - before; result.CompressionRatio = CompressionUtility.GetCompressionRatio(randBytes).Result; results.Add(result); Console.WriteLine((after - before).ToString()); Console.Write("Sleeping to allow pool to fill..."); Thread.Sleep(3000); // Should be enough time for its pool to fill up, so it won't slow down next: Console.WriteLine(" Done."); //ThreadedSeedGenerator(fast) result = new RandomResult(); result.AlgorithmName = "ThreadedSeedGenerator(fast)"; Console.Write(result.AlgorithmName + " "); var myThreadedSeedGenerator = new ThreadedSeedGenerator(); Array.Clear(randBytes, 0, randBytesLength); before = DateTime.Now; randBytes = myThreadedSeedGenerator.GenerateSeed(randBytesLength, true); after = DateTime.Now; result.TimeSpan = after - before; result.CompressionRatio = CompressionUtility.GetCompressionRatio(randBytes).Result; results.Add(result); Console.WriteLine((after - before).ToString()); //ThreadedSeedGenerator(slow) result = new RandomResult(); result.AlgorithmName = "ThreadedSeedGenerator(slow)"; Console.Write(result.AlgorithmName + " "); Array.Clear(randBytes, 0, randBytesLength); before = DateTime.Now; randBytes = myThreadedSeedGenerator.GenerateSeed(randBytesLength, false); after = DateTime.Now; result.TimeSpan = after - before; result.CompressionRatio = CompressionUtility.GetCompressionRatio(randBytes).Result; results.Add(result); Console.WriteLine((after - before).ToString()); //ThreadSchedulerRNG(slow) result = new RandomResult(); result.AlgorithmName = "ThreadSchedulerRng"; Console.Write(result.AlgorithmName + " "); before = DateTime.Now; var myThreadSchedulerRNG = new ThreadSchedulerRng(); myThreadSchedulerRNG.GetBytes(randBytes); after = DateTime.Now; result.TimeSpan = after - before; result.CompressionRatio = CompressionUtility.GetCompressionRatio(randBytes).Result; results.Add(result); Console.WriteLine((after - before).ToString()); const int numResults = 14; Console.Write("ticks bit positions "); before = DateTime.Now; var ticksResults = new RandomResult[numResults]; var ticksResultsBytes = new byte[numResults][]; for (var i = 0; i < numResults; i++) { ticksResults[i] = new RandomResult { AlgorithmName = "ticks bit #" + i.ToString().PadLeft(2) }; ticksResultsBytes[i] = new byte[randBytesLength]; } for (var i = 0; i < randBytesLength; i++) { for (var j = 0; j < 8; j++) { var ticks = DateTime.Now.Ticks; for (var bitPos = 0; bitPos < numResults; bitPos++) { ticksResultsBytes[bitPos][i] <<= 1; ticksResultsBytes[bitPos][i] += (byte)(ticks % 2); ticks >>= 1; } Thread.Sleep(1); } } after = DateTime.Now; for (var i = 0; i < numResults; i++) { ticksResults[i].TimeSpan = after - before; ticksResults[i].CompressionRatio = CompressionUtility.GetCompressionRatio(ticksResultsBytes[i]).Result; results.Add(ticksResults[i]); } Console.WriteLine((after - before).ToString()); Console.Write("Sleeping to allow pool to fill..."); Thread.Sleep(15000); // Should be enough time for its pool to fill up, so it won't slow down next: Console.WriteLine(" Done."); // I want to test each of the ThreadedSeedGeneratorRng and ThreadSchedulerRng prior to doing TinHatRandom // or TinHatURandom, because otherwise, TinHatRandom will create static instances of them, which race, etc. // thus throwing off my benchmark results. //SafeRandom result = new RandomResult { AlgorithmName = "SafeRandom" }; Console.Write(result.AlgorithmName + " "); before = DateTime.Now; randBytes = SafeRandom.StaticInstance.GetBytes(randBytes.Length); after = DateTime.Now; result.TimeSpan = after - before; result.CompressionRatio = CompressionUtility.GetCompressionRatio(randBytes).Result; results.Add(result); Console.WriteLine((after - before).ToString()); Console.Write("Sleeping to allow pool to fill..."); Thread.Sleep(15000); // Should be enough time for its pool to fill up, so it won't slow down next: Console.WriteLine(" Done."); result = new RandomResult { AlgorithmName = "FastRandom" }; Console.Write(result.AlgorithmName + " "); before = DateTime.Now; randBytes = FastRandom.StaticInstance.GetBytes(randBytes.Length); after = DateTime.Now; result.TimeSpan = after - before; result.CompressionRatio = CompressionUtility.GetCompressionRatio(randBytes).Result; results.Add(result); Console.WriteLine((after - before).ToString()); Console.Write("Sleeping to allow pool to fill..."); Thread.Sleep(15000); // Should be enough time for its pool to fill up, so it won't slow down next: Console.WriteLine(" Done."); Console.WriteLine(""); var maxCompressionRatio = double.MinValue; var minCompressionRatio = double.MaxValue; var longestName = 0; foreach (var theResult in results) { if (theResult.AlgorithmName.Length > longestName) { longestName = theResult.AlgorithmName.Length; } if (theResult.CompressionRatio < minCompressionRatio) { minCompressionRatio = theResult.CompressionRatio; } if (theResult.CompressionRatio > maxCompressionRatio) { maxCompressionRatio = theResult.CompressionRatio; } } Console.WriteLine("AlgorithmName".PadLeft(longestName) + " : bits per bit : elapsed sec : effective rate"); foreach (var theResult in results) { var bitsPerBit = (theResult.CompressionRatio - minCompressionRatio) / (maxCompressionRatio - minCompressionRatio); double byteRate; string byteRateString; if (theResult.TimeSpan.TotalSeconds == 0) { if (theResult.CompressionRatio == minCompressionRatio) { byteRateString = "0"; } else { byteRateString = "infinity"; } } else { byteRate = bitsPerBit * randBytesLength / theResult.TimeSpan.TotalSeconds; if (byteRate > 1000000) { byteRateString = (byteRate / 1000000).ToString("F2") + " MiB/sec"; } else if (byteRate > 1000) { byteRateString = (byteRate / 1000).ToString("F2") + " KiB/sec"; } else { byteRateString = byteRate.ToString("F2") + " B/sec"; } } Console.WriteLine(theResult.AlgorithmName.PadLeft(longestName) + " : " + bitsPerBit.ToString("0.000").PadLeft(12) + " : " + theResult.TimeSpan.TotalSeconds.ToString("0.000").PadLeft(11) + " : " + byteRateString.PadLeft(14)); } Console.WriteLine(""); Console.Error.WriteLine("Finished"); Console.Out.Flush(); Console.ReadKey(); }