【问题标题】:How to create random data efficiently如何有效地创建随机数据
【发布时间】:2018-04-06 14:40:45
【问题描述】:

我正在创建随机字节数组来测试一些传输层。我曾经传输这样创建的数据

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

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

因为Read() 被多次调用,并且每次创建一个新的字节数组并用随机数据填充它可能会很慢,所以我想提出一个解决方案,它不会在每次调用中使用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];
  }
}
}

调用代码如下所示:

private static readonly MyBuffer SBuffer = new MyBuffer();
private static byte[] array = new byte[0];

public byte[] Read(Data data) {

  int size = data.ChunkSize;

  if (array.Length != size)
  {
    array = new byte[size];
  }

  Array.Copy(SBuffer.Latest(size).ToArray(), array, size);
  return array;
}

但这比我的第一次尝试更慢(慢得多),我真的不明白为什么。任何人都可以告诉我我的代码在哪里效率低下,或者想出任何其他有效的解决方案来解决我的问题?

谢谢

【问题讨论】:

  • 您真的遇到了 Random NextBytes 的性能问题吗?如果是这样,它必须快多少?此外,将您的 Random 实例移到方法之外。
  • @FCin 澄清一下:我在服务器上创建此随机数据并通过以太网将其发送到客户端。我想对我们的传输层进行基准测试,从而确保数组的创建和填充不是我测量数据传输时的瓶颈。
  • 创建随机字节非常快......比复制数组块并尝试连接它们要快得多。
  • @MatthewWatson 我刚刚创建了一个小控制台应用程序,它创建了一个新的字节数组并用随机数据填充它(我的第一种方法),在我的服务器上创建 10 个 90mb 大小的数组需要 18 秒.
  • 为什么你需要这么多伪随机数却不能重用文件或者至少修改一点文件?

标签: c# arrays random


【解决方案1】:

如果您不太关心随机数据的质量,您可以编写自己的使用简单线性同余生成的 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;
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-10-16
    • 2021-08-01
    • 1970-01-01
    • 2012-01-06
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    相关资源
    最近更新 更多