この議論を検討するために、彼らがこのベンチマークをどのように作成したかについて注意深くなければ、彼らは簡単に誤解される可能性があります。私はこれを説明するために非常に簡単なテストを書きました。以下のテストでは、Buffer.BlockCopyを最初に開始するかArray.Copyを開始するかをテストの順序で入れ替えると、ほとんどの場合、最初の方が遅くなります(近いものです)。これは、さまざまな理由により、単純にテストを複数回実行するのではなく、次々と正確な結果が得られないことを意味します。
1000000の連続するdoubleの配列に対して、1000000試行ごとにテストをそのまま維持することに頼りました。しかし、私は最初の900000サイクルを無視し、残りを平均します。その場合、バッファは優れています。
private static void BenchmarkArrayCopies()
{
long[] bufferRes = new long[1000000];
long[] arrayCopyRes = new long[1000000];
long[] manualCopyRes = new long[1000000];
double[] src = Enumerable.Range(0, 1000000).Select(x => (double)x).ToArray();
for (int i = 0; i < 1000000; i++)
{
bufferRes[i] = ArrayCopyTests.ArrayBufferBlockCopy(src).Ticks;
}
for (int i = 0; i < 1000000; i++)
{
arrayCopyRes[i] = ArrayCopyTests.ArrayCopy(src).Ticks;
}
for (int i = 0; i < 1000000; i++)
{
manualCopyRes[i] = ArrayCopyTests.ArrayManualCopy(src).Ticks;
}
Console.WriteLine("Loop Copy: {0}", manualCopyRes.Average());
Console.WriteLine("Array.Copy Copy: {0}", arrayCopyRes.Average());
Console.WriteLine("Buffer.BlockCopy Copy: {0}", bufferRes.Average());
//more accurate results - average last 1000
Console.WriteLine();
Console.WriteLine("----More accurate comparisons----");
Console.WriteLine("Loop Copy: {0}", manualCopyRes.Where((l, i) => i > 900000).ToList().Average());
Console.WriteLine("Array.Copy Copy: {0}", arrayCopyRes.Where((l, i) => i > 900000).ToList().Average());
Console.WriteLine("Buffer.BlockCopy Copy: {0}", bufferRes.Where((l, i) => i > 900000).ToList().Average());
Console.ReadLine();
}
public class ArrayCopyTests
{
private const int byteSize = sizeof(double);
public static TimeSpan ArrayBufferBlockCopy(double[] original)
{
Stopwatch watch = new Stopwatch();
double[] copy = new double[original.Length];
watch.Start();
Buffer.BlockCopy(original, 0 * byteSize, copy, 0 * byteSize, original.Length * byteSize);
watch.Stop();
return watch.Elapsed;
}
public static TimeSpan ArrayCopy(double[] original)
{
Stopwatch watch = new Stopwatch();
double[] copy = new double[original.Length];
watch.Start();
Array.Copy(original, 0, copy, 0, original.Length);
watch.Stop();
return watch.Elapsed;
}
public static TimeSpan ArrayManualCopy(double[] original)
{
Stopwatch watch = new Stopwatch();
double[] copy = new double[original.Length];
watch.Start();
for (int i = 0; i < original.Length; i++)
{
copy[i] = original[i];
}
watch.Stop();
return watch.Elapsed;
}
}
https://github.com/chivandikwa/Random-Benchmarks
Marshal.Copy
:-)をお忘れなく。まあ、Array.Copy
参照型、複雑な値型、および型が変わらない場合は、Buffer.BlockCopy
値型、バイト配列、およびバイトマジック間の「変換」に使用します。F.ex. との組み合わせStructLayout
は、何をしているのかわかっている場合は非常に強力です。パフォーマンスに関しては、管理されていないmemcpy
/ への呼び出しがcpblk
最も速いようです-code4k.blogspot.nl/2010/10/…を参照してください。