答えは、ガベージコレクターが実行されており、タイミングが変更されていることだと思います。
免責事項:コンパイル可能な例を投稿していないため、OP コードのコンテキスト全体を確認できません。配列を再利用するのではなく、再割り当てしていると思います。そうでない場合、これは正解ではありません。
次のコードを検討してください。
using System;
using System.Diagnostics;
namespace Demo
{
internal class Program
{
private static void Main(string[] args)
{
var ar = new int[500000000];
test1(ar);
//ar = new int[500000000]; // Uncomment this line.
test2(ar);
}
private static void test1(int[] ar)
{
var sw = new Stopwatch();
sw.Start();
var length = ar.Length;
for (var i = 0; i < length; i++)
{
if (ar[i] == 0);
}
sw.Stop();
Console.WriteLine("test1 took " + sw.Elapsed);
}
private static void test2(int[] ar)
{
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < ar.Length; i++)
{
if (ar[i] == 0);
}
sw.Stop();
Console.WriteLine("test2 took " + sw.Elapsed);
}
}
}
私のシステムでは、次のように出力されます。
test1 took 00:00:00.6643788
test2 took 00:00:00.3516378
マークされた行のコメントを外すと// Uncomment this line.
、タイミングが次のように変わります。
test1 took 00:00:00.6615819
test2 took 00:00:00.6806489
これは、GC が前の配列を収集するためです。
[編集] JIT の起動コストを回避するために、テスト全体をループに入れました。
for (int i = 0; i < 8; ++i)
{
test1(ar);
ar = new int[500000000]; // Uncomment this line.
test2(ar);
}
そして、2番目の配列割り当てをコメントアウトした結果は次のとおりです。
test1 took 00:00:00.6437912
test2 took 00:00:00.3534027
test1 took 00:00:00.3401437
test2 took 00:00:00.3486296
test1 took 00:00:00.3470775
test2 took 00:00:00.3675475
test1 took 00:00:00.3501221
test2 took 00:00:00.3549338
test1 took 00:00:00.3427057
test2 took 00:00:00.3574063
test1 took 00:00:00.3566458
test2 took 00:00:00.3462722
test1 took 00:00:00.3430952
test2 took 00:00:00.3464017
test1 took 00:00:00.3449196
test2 took 00:00:00.3438316
2 番目の配列割り当てを有効にすると、次のようになります。
test1 took 00:00:00.6572665
test2 took 00:00:00.6565778
test1 took 00:00:00.3576911
test2 took 00:00:00.6910897
test1 took 00:00:00.3464013
test2 took 00:00:00.6638542
test1 took 00:00:00.3548638
test2 took 00:00:00.6897472
test1 took 00:00:00.4464020
test2 took 00:00:00.7739877
test1 took 00:00:00.3835624
test2 took 00:00:00.8432918
test1 took 00:00:00.3496910
test2 took 00:00:00.6471341
test1 took 00:00:00.3486505
test2 took 00:00:00.6527160
GC のため、test2 は一貫して時間がかかることに注意してください。
残念ながら、GC はタイミングの結果をほとんど意味のないものにします。
たとえば、テスト コードを次のように変更するとします。
for (int i = 0; i < 8; ++i)
{
var ar = new int[500000000];
GC.Collect();
test1(ar);
//ar = new int[500000000]; // Uncomment this line.
test2(ar);
}
行をコメントアウトすると、次のようになります。
test1 took 00:00:00.6354278
test2 took 00:00:00.3464486
test1 took 00:00:00.6672933
test2 took 00:00:00.3413958
test1 took 00:00:00.6724916
test2 took 00:00:00.3530412
test1 took 00:00:00.6606178
test2 took 00:00:00.3413083
test1 took 00:00:00.6439316
test2 took 00:00:00.3404499
test1 took 00:00:00.6559153
test2 took 00:00:00.3413563
test1 took 00:00:00.6955377
test2 took 00:00:00.3364670
test1 took 00:00:00.6580798
test2 took 00:00:00.3378203
そして、コメントを外して:
test1 took 00:00:00.6340203
test2 took 00:00:00.6276153
test1 took 00:00:00.6813719
test2 took 00:00:00.6264782
test1 took 00:00:00.6927222
test2 took 00:00:00.6269447
test1 took 00:00:00.7010559
test2 took 00:00:00.6262000
test1 took 00:00:00.6975080
test2 took 00:00:00.6457846
test1 took 00:00:00.6796235
test2 took 00:00:00.6341214
test1 took 00:00:00.6823508
test2 took 00:00:00.6455403
test1 took 00:00:00.6856985
test2 took 00:00:00.6430923
このテストの教訓は次のとおりだと思います。この特定のテストの GC は、コードの残りの部分と比較して非常に大きなオーバーヘッドであるため、タイミングの結果を完全にゆがめており、何の意味も信頼できません。