基本的にオフセットとカウントの観点から ArraySegment によって保持されるセグメントを返す方法について調べてきました。ArraySegment は完全な元の配列を保持しますが、セグメントへの変更が元の配列に反映されるという事実でそれを区切るだけです。ArraySegment の問題または制限は、セグメント自体が全体として返されず、値をトラバースする必要があることです。セグメント全体を返す最良の方法は何ですか?
byte[] input = new byte[5]{1,2,3,4,5};
ArraySegment<byte> delimited = new ArraySegment<byte>(input,0,2);
byte[] segment = HERE I NEED SOMETHING THAT WILL RETURN THE SEGMENT i.e. [0,1,2]
最も重要な点は、セグメントはコピーであってはならず、元の配列を参照する必要があるということです。セグメントに何らかの変更を加えた場合は、元の配列に反映する必要があります。
どんなヒントでも大歓迎です、ありがとう!
課題のベンチマーク: ThomasとdigEmAllからのいくつかの回答の後
わかりました、digEmAll と Thomas のコードに対していくつかのベンチマークを実行しましたが、驚いたことに、コードは圧倒的に高速です。まさに私が必死に探していたもの。これが結果です。
Construct Size Elements assigned Iterations Time
_______________________________________________________________________________
ArraySegmentWrapper 1500 1500 1000000 396.3 ms
Array.Copy 1500 1500 1000000 4389.04 ms
途方もない違いを見ることができるように、ArraySegment のコードを使用することは非常に明確です。以下はベンチマークコードです。「new」がループ内に入れられた理由について人々が主張するため、これは少し偏っている可能性があることに注意してください。コードの多くを移動せずに、現在手元にある状況を可能な限り再現しようとしています。これは私の一日を作りました!
namespace ArraySegmentWrapped
{
class Program
{
public static Stopwatch stopWatch = new Stopwatch();
public static TimeSpan span = new TimeSpan();
public static double totalTime = 0.0;
public static int iterations = 1000000;
static void Main(string[] args)
{
int size = 1500;
int startIndex = 0;
int endIndex = 1499;
byte[] array1 = new byte[size];
byte[] array2 = null;
for (int index = startIndex; index < size; index++)
{
array1[index] = (byte)index;
}
ArraySegmentWrapper<byte> arraySeg;
for (int index = 0; index < iterations; index++)
{
stopWatch.Start();
arraySeg = new ArraySegmentWrapper<byte>(array1, startIndex, endIndex);
stopWatch.Stop();
totalTime += stopWatch.Elapsed.TotalMilliseconds;
}
Console.WriteLine("ArraySegment:{0:F6}", totalTime / iterations);
stopWatch.Reset();
totalTime = 0.0;
for (int index = 0; index < iterations; index++)
{
stopWatch.Start();
array2 = new byte[endIndex - startIndex + 1];
Array.Copy(array1, startIndex, array2, 0, endIndex);
stopWatch.Stop();
totalTime += stopWatch.Elapsed.TotalMilliseconds;
}
Console.WriteLine("Array.Copy:{0:F6}", totalTime / iterations);
}
}
// Code for ArraySegmentWrapper goes here
}
アクセス ベンチマーク (更新) Thomasがベンチマークについて指摘し、単純な配列へのアクセスは ArraySegmentに比べて高速であると言った後、彼は完全に正しかった。しかし、リリース モードでテストする必要があることを digEmAll が指摘したので (デバッグ モードでのテストの古い間違いで申し訳ありません)、コードを上記とほぼ同じままにしました (反復をゼロ 2 つ減らしました - 出力が完了するまで非常に長く待つことができませんでした申し訳ありません)と同じ数の要素にアクセスするためのいくつかの変更、以下は私が得たものです。
Construct Size Elements accessed Iterations Time
_______________________________________________________________________________
ArraySegmentWrapper 1500 1500 1000000 5268.3 ms
Array.Copy 1500 1500 1000000 4812.4 ms
割り当ては非常に高速ですが、ArraySegments を介したアクセスは遅いと結論付けました。