如何有效地创建随机数据

时间:2017-10-25 13:20:41

标签: c# arrays random

我正在创建随机字节数组来测试某些传输层。我过去常常传输像这样创建的数据

 public byte[] Read(Data data) {
  var rnd = new Random();
  int size = data.ChunkSize;

  byte[] array = new byte[size];
  rnd.NextBytes(array);
  return array;
}

因为多次调用Read(),并且每次创建一个新的字节数组并用随机数据填充它可能会很慢,我想提出一个不使用{{1}的解决方案在每次通话中。

所以我想出了一个Class,它包含一个静态随机数组并从中读取。当它到达该数组的末尾时,它将从头开始:

rnd.NextBytes

,调用代码如下所示:

public class MyBuffer
{
private static readonly Random SRandom = new Random();

private readonly byte[] buffer = new byte[5000000]; // 5mb array with random data to read from
private int currentStart;

public MyBuffer()
{
  SRandom.NextBytes(buffer);
}

public IEnumerable<byte> Latest(int amountOfBytes)
{
  return FetchItems(amountOfBytes).ToArray();
}

private IEnumerable<byte> FetchItems(int amountOfBytes)
{
  IEnumerable<byte> fetchedItems = Enumerable.Empty<byte>();
  int total = 0;

  while (total < amountOfBytes)
  {
    int min = Math.Min(amountOfBytes, buffer.Length - currentStart);
    fetchedItems = fetchedItems.Concat(FetchItems(currentStart, min));

    total += min;
    currentStart += min;
    currentStart = currentStart % buffer.Length;
  }

  return fetchedItems;
}
private IEnumerable<byte> FetchItems(int start, int end)
{
  for (int i = start; i < end; i++)
  {
    yield return buffer[i];
  }
}
}

但事实证明这比我的第一次尝试更慢(速度慢),我真的不明白为什么。任何人都可以告诉我我的代码效率低下或者为我的问题提出任何其他有效的解决方案吗?

由于

1 个答案:

答案 0 :(得分:0)

如果您不太关心随机数据的质量,您可以编写自己的RNG,使用简单的线性同余生成:

public static int FillWithRandomData(int seed, byte[] array)
{
    unchecked
    {
        int n = seed * 134775813 + 1;

        for (int i = 0; i < array.Length; ++i)
        {
            array[i] = (byte) n;
            n = 2147483629 * n + 2147483587;
        }

        return n;
    }
}

这很快,虽然它没有很长的时间 - 但我认为这足以达到你的目的。

如果你计算时间,请确保你的发布版本不是调试版本。

当我计时时,它比使用Random.NextBytes()快七倍。

您可以在调用种子时使用Random创建种子,或者只传递上一次调用的返回值。

这是我的完整测试应用程序:

using System;
using System.Diagnostics;

namespace Demo
{
    public class Program
    {
        static void Main()
        {
            byte[] data = new byte[90 * 1024 * 1024];

            Stopwatch sw = Stopwatch.StartNew();

            int seed = (int) DateTime.Now.Ticks;

            for (int i = 0; i < 10; ++i)
                seed = FillWithRandomData(seed, data);

            Console.WriteLine(sw.Elapsed);
        }

        public static int FillWithRandomData(int seed, byte[] array)
        {
            unchecked
            {
                int n = seed * 134775813 + 1;

                for (int i = 0; i < array.Length; ++i)
                {
                    array[i] = (byte) n;
                    n = 2147483629 * n + 2147483587;
                }

                return n;
            }
        }
    }
}