要权衡这一论点,如果不注意他们如何编写此基准,很容易被误导。我写了一个非常简单的测试来说明这一点。在下面的测试中,如果我在先启动Buffer.BlockCopy或Array.Copy之间交换测试顺序,则最先执行的顺序几乎总是最慢的(尽管接近)。这意味着出于种种原因,我不会简单地多次运行测试,尤其是一次又一次地运行测试,而不会给出准确的结果。
我采取的措施是按1000000次尝试对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/...。