对于ValueApple[]
vs ReferenceApple[]
; 具体差异很大程度上取决于目标平台;在 x86 上,它在引用类型数组中似乎确实有一些开销,但在 x64 上却不太明显(尽管该版本现在复制了两倍的数据,但它比任何一个x86 版本都快):ReferenceApple[]
x86
ValueApple: 3295ms
ValueApple CopyTo: 3283ms
ReferenceApple: 4345ms
ReferenceApple CopyTo: 4234ms
x64
ValueApple: 1819ms
ValueApple CopyTo: 1864ms
ReferenceApple: 2251ms
ReferenceApple CopyTo: 2335ms
我不会说这值得弯曲代码。您还需要问:“数组复制是我真正的瓶颈吗?”。如果不是,这个测试完全没有帮助。所以首先:找到你的瓶颈是什么。
在某些情况下,结构数组技巧可能会有所帮助,但通常这与涉及长期大量数据的非常极端的高内存/垃圾收集场景更相关。不是具有 20/40 项数组的常规代码。
以上数字基于:
using System;
using System.Diagnostics;
struct ValueApple
{
public int Redness;
}
class ReferenceApple
{
public int Redness;
}
static class Program {
static void Main()
{
const int LOOP = 50000000;
ValueApple[] a1 = new ValueApple[20];
ValueApple[] a2 = new ValueApple[40];
var watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
Array.Copy(a1, a2, 20);
}
watch.Stop();
Console.WriteLine("ValueApple: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
a1.CopyTo(a2, 0);
}
watch.Stop();
Console.WriteLine("ValueApple CopyTo: {0}ms", watch.ElapsedMilliseconds);
ReferenceApple[] a3 = new ReferenceApple[20];
ReferenceApple[] a4 = new ReferenceApple[40];
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
Array.Copy(a3, a4, 20);
}
watch.Stop();
Console.WriteLine("ReferenceApple: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
a3.CopyTo(a4, 0);
}
watch.Stop();
Console.WriteLine("ReferenceApple CopyTo: {0}ms", watch.ElapsedMilliseconds);
Console.WriteLine("(done)");
Console.ReadKey();
}
}
对于包装与不包装:
我质疑你的结果;我的号码:
Wrapper<T>: 2175ms
Direct: 2231ms
Wrapper: 2165ms
(最后一个是相同的非通用版本)
这基本上是“大致相同,给予或接受随机 CPU 活动”。几毫秒超过 50M 的迭代当然不值得让代码变形...
重要的是,确保任何此类测试都处于发布模式,并在调试器之外执行。
我的测试代码:
using System;
using System.Diagnostics;
struct ValueWrapper<T> {
public T Value;
}
struct ValueWrapper
{
public Apple Value;
}
class Apple { }
static class Program {
static void Main()
{
const int LOOP = 50000000;
ValueWrapper<Apple>[] a1 = new ValueWrapper<Apple>[20];
ValueWrapper<Apple>[] a2 = new ValueWrapper<Apple>[40];
var watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
Array.Copy(a1, a2, 20);
}
watch.Stop();
Console.WriteLine("Wrapper<T>: {0}ms", watch.ElapsedMilliseconds);
Apple[] a3 = new Apple[20];
Apple[] a4 = new Apple[40];
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
Array.Copy(a3, a4, 20);
}
watch.Stop();
Console.WriteLine("Direct: {0}ms", watch.ElapsedMilliseconds);
ValueWrapper[] a5 = new ValueWrapper[20];
ValueWrapper[] a6 = new ValueWrapper[40];
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
Array.Copy(a5, a6, 20);
}
watch.Stop();
Console.WriteLine("Wrapper: {0}ms", watch.ElapsedMilliseconds);
Console.WriteLine("(done)");
Console.ReadKey();
}
}