ValueApple[]
対ReferenceApple[]
; _ 特定の違いは、ターゲットプラットフォームに大きく依存します。x86では、参照型配列に少しオーバーヘッドがあるように見えますが、x64ではそれほど目立ちません(バージョンが2倍のデータをコピーしているにもかかわらず、どちらの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アクティビティを与えるか取る」です。5,000万回の反復で数ミリ秒かかることは、コードを形を崩して曲げる価値がないことは確かです...
重要なのは、そのようなテストがリリースモードであり、デバッガーの外部で実行されていることを確認することです。
私のテストコード:
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();
}
}