I think the answer is that the garbage collector works and changes your timings.
Disclaimer : I do not see the whole context of the OP code because you did not publish the compiled example; I assume that you are redistributing the array and not reusing it. If not, then this is not the right answer!
Consider this code:
using System; using System.Diagnostics; namespace Demo { internal class Program { private static void Main(string[] args) { var ar = new int[500000000]; test1(ar);
On my system, it prints:
test1 took 00:00:00.6643788 test2 took 00:00:00.3516378
If I uncommented the line marked // Uncomment this line. , then the timings change to:
test1 took 00:00:00.6615819 test2 took 00:00:00.6806489
This is because GC collects the previous array.
[EDIT] To avoid the cost of running JIT, I put the whole test in a loop:
for (int i = 0; i < 8; ++i) { test1(ar); ar = new int[500000000];
And then my results with the allocation of the second array:
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
And with the second array distribution turned on:
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
Note that test2 sequentially takes longer due to the GC.
Unfortunately, GC makes the synchronization results pretty pointless.
For example, if I change the test code to this:
for (int i = 0; i < 8; ++i) { var ar = new int[500000000]; GC.Collect(); test1(ar);
With a commented line, I get:
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
And without it:
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
I think the moral of this test is: GC for this particular test is such a big overhead compared to the rest of the code that it completely distorts the synchronization results and cannot be trusted to mean anything.