Why is this faster on 64 bit than 32 bit?

x64 processors contain 64 bit general purpose registers with which they can calculate operations on 64 bit integers in a single instruction. 32 bit processors does not have that. This is especially relevant to your program as it’s heavily using long (64-bit integer) variables.

For instance, in x64 assembly, to add a couple 64 bit integers stored in registers, you can simply do:

; adds rbx to rax
add rax, rbx

To do the same operation on a 32 bit x86 processor, you’ll have to use two registers and manually use the carry of the first operation in the second operation:

; adds ecx:ebx to edx:eax
add eax, ebx
adc edx, ecx

More instructions and less registers mean more clock cycles, memory fetches, … which will ultimately result in reduced performance. The difference is very notable in number crunching applications.

For .NET applications, it seems that the 64-bit JIT compiler performs more aggressive optimizations improving overall performance.

Regarding your point about array iteration, the C# compiler is clever enough to recognize foreach over arrays and treat them specially. The generated code is identical to using a for loop and it’s in recommended that you use foreach if you don’t need to change the array element in the loop. Besides that, the runtime recognizes the pattern for (int i = 0; i < a.Length; ++i) and omits the bound checks for array accesses inside the loop. This will not happen in the LongLength case and will result in decreased performance (both for 32 bit and 64 bit case); and since you’ll be using long variables with LongLength, the 32 bit performance will get degraded even more.

Leave a Comment