2017-10-25 18 views
1

トランスポート層をテストするためにランダムなバイト配列を作成していました。私は、Read()は私が解決策を考え出すしたい、何度も呼ばれ、新しいバイト配列を作成するたびにランダムデータでそれを埋めることは遅くなる可能性があるため、このランダムなデータを効率的に作成する方法

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

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

のように作成したデータを転送するために使用されていますすべての呼び出しで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; 
} 

しかし、これはさらに遅く(な方法であることが判明し、それがその配列の最後に来るとき、それは再び最初から開始します私の最初の試みよりも遅い)、なぜ私は本当に見ることができません。誰かが私のコードが非効率的であるか、私の問題の他の効率的な解決策を考え出すことができますか?

おかげ

+0

は、あなたが実際にランダム 'NextBytes'でパフォーマンスの問題がありましたか?もしそうなら、どれくらい早くする必要がありますか?また、メソッドの外で 'ランダム'インスタンシエーションを移動します。 – FCin

+0

@FCin明確にするには:このランダムなデータをサーバーに作成し、それをイーサネット経由でクライアントに送信する。データ転送を測定する際に、アレイの作成と充填がボトルネックではないことを確認します。 – user3292642

+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()を使用するよりも約7倍速いです。

コールするときに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; 
      } 
     } 
    } 
} 
関連する問題