私は単純なベンチマークをThreadStatic
実行し、質問で説明されている単純なパラメーターのパフォーマンスが向上しています。
反復回数が多い多くのアルゴリズムと同様に、新しい配列を割り当てるバージョンでは、GCオーバーヘッドがそれを強制終了する単純なケースだと思います。
アップデート
最小限の配列参照の使用をモデル化するための配列の追加の反復を含むテスト、およびThreadStatic
参照がローカルにコピーされた以前のテストに加えて、配列参照の使用:
Iterations : 10,000,000
Local ArrayRef (- array iteration) : 330.17ms
Local ArrayRef (- array iteration) : 327.03ms
Local ArrayRef (- array iteration) : 1382.86ms
Local ArrayRef (- array iteration) : 1425.45ms
Local ArrayRef (- array iteration) : 1434.22ms
TS CopyArrayRefLocal (- array iteration) : 107.64ms
TS CopyArrayRefLocal (- array iteration) : 92.17ms
TS CopyArrayRefLocal (- array iteration) : 92.42ms
TS CopyArrayRefLocal (- array iteration) : 92.07ms
TS CopyArrayRefLocal (- array iteration) : 92.10ms
Local ArrayRef (+ array iteration) : 1740.51ms
Local ArrayRef (+ array iteration) : 1647.26ms
Local ArrayRef (+ array iteration) : 1639.80ms
Local ArrayRef (+ array iteration) : 1639.10ms
Local ArrayRef (+ array iteration) : 1646.56ms
TS CopyArrayRefLocal (+ array iteration) : 368.03ms
TS CopyArrayRefLocal (+ array iteration) : 367.19ms
TS CopyArrayRefLocal (+ array iteration) : 367.22ms
TS CopyArrayRefLocal (+ array iteration) : 368.20ms
TS CopyArrayRefLocal (+ array iteration) : 367.37ms
TS TSArrayRef (+ array iteration) : 360.45ms
TS TSArrayRef (+ array iteration) : 359.97ms
TS TSArrayRef (+ array iteration) : 360.48ms
TS TSArrayRef (+ array iteration) : 360.03ms
TS TSArrayRef (+ array iteration) : 359.99ms
コード:
[ThreadStatic]
private static int[] _array;
[Test]
public object measure_thread_static_performance()
{
const int TestIterations = 5;
const int Iterations = (10 * 1000 * 1000);
const int ArraySize = 50;
Action<string, Action> time = (name, test) =>
{
for (int i = 0; i < TestIterations; i++)
{
TimeSpan elapsed = TimeTest(test, Iterations);
Console.WriteLine("{0} : {1:F2}ms", name, elapsed.TotalMilliseconds);
}
};
int[] array = null;
int j = 0;
Action test1 = () =>
{
array = new int[ArraySize];
};
Action test2 = () =>
{
array = _array ?? (_array = new int[ArraySize]);
};
Action test3 = () =>
{
array = new int[ArraySize];
for (int i = 0; i < ArraySize; i++)
{
j = array[i];
}
};
Action test4 = () =>
{
array = _array ?? (_array = new int[ArraySize]);
for (int i = 0; i < ArraySize; i++)
{
j = array[i];
}
};
Action test5 = () =>
{
array = _array ?? (_array = new int[ArraySize]);
for (int i = 0; i < ArraySize; i++)
{
j = _array[i];
}
};
Console.WriteLine("Iterations : {0:0,0}\r\n", Iterations);
time("Local ArrayRef (- array iteration)", test1);
time("TS CopyArrayRefLocal (- array iteration)", test2);
time("Local ArrayRef (+ array iteration)", test3);
time("TS CopyArrayRefLocal (+ array iteration)", test4);
time("TS TSArrayRef (+ array iteration)", test5);
Console.WriteLine(j);
return array;
}
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect")]
private static TimeSpan TimeTest(Action action, int iterations)
{
Action gc = () =>
{
GC.Collect();
GC.WaitForFullGCComplete();
};
Action empty = () => { };
Stopwatch stopwatch1 = Stopwatch.StartNew();
for (int j = 0; j < iterations; j++)
{
empty();
}
TimeSpan loopElapsed = stopwatch1.Elapsed;
gc();
action(); //JIT
action(); //Optimize
Stopwatch stopwatch2 = Stopwatch.StartNew();
for (int j = 0; j < iterations; j++) action();
gc();
TimeSpan testElapsed = stopwatch2.Elapsed;
return (testElapsed - loopElapsed);
}