Huge performance difference in byte array between x64 and x86

I am currently doing micro-benchmarks to better understand performance issues and the CLR version. The microcontrol test is an xoring array with two bytes out of every 64 bytes together.

I always make a referenced implementation with secure .net before trying to outperform the implementation of .net framework with unsafe, etc.

My reference implementation:

for (int p = 0; p < 64; p++)
    a[p] ^= b[p];

where aboth bare and are byte[] a = new byte[64]filled with data from .NET rng.

This code runs on x64 twice as fast as on x86. At first I thought it was normal because jit do something like *long^=*longand *int^=*inton x86.

But my optimized unsafe version:

fixed (byte* pA = a)
fixed (byte* pB = b)
{
    long* ppA = (long*)pA;
    long* ppB = (long*)pB;

    for (int p = 0; p < 8; p++)
    {
        *ppA ^= *ppB;

        ppA++;
        ppB++;
    }
}

4 , x64- . *long^=*long *int^=*int .

? , ASM: # x86 ?

IL- x86 x64 ( ):

IL_0059: ldloc.3
IL_005a: ldloc.s p
IL_005c: ldelema [mscorlib]System.Byte
IL_0061: dup
IL_0062: ldobj [mscorlib]System.Byte
IL_0067: ldloc.s b
IL_0069: ldloc.s p
IL_006b: ldelem.u1
IL_006c: xor
IL_006d: conv.u1
IL_006e: stobj [mscorlib]System.Byte
IL_0073: ldloc.s p
IL_0075: ldc.i4.1
IL_0076: add
IL_0077: stloc.s p

IL_0079: ldloc.s p
IL_007b: ldc.i4.s 64
IL_007d: blt.s IL_0059

, ldloc.3 a.

ASM x86:

                for (int p = 0; p < 64; p++)
010900DF  xor         edx,edx
010900E1  mov         edi,dword ptr [ebx+4]
                    a[p] ^= b[p];
010900E4  cmp         edx,edi
010900E6  jae         0109010C
010900E8  lea         esi,[ebx+edx+8]
010900EC  mov         eax,dword ptr [ebp-14h]
010900EF  cmp         edx,dword ptr [eax+4]
010900F2  jae         0109010C
010900F4  movzx       eax,byte ptr [eax+edx+8]
010900F9  xor         byte ptr [esi],al
                for (int p = 0; p < 64; p++)
010900FB  inc         edx
010900FC  cmp         edx,40h
010900FF  jl          010900E4

ASM x64:

                    a[p] ^= b[p];
00007FFF4A8B01C6  mov         eax,3Eh
00007FFF4A8B01CB  cmp         rax,rcx
00007FFF4A8B01CE  jae         00007FFF4A8B0245
00007FFF4A8B01D0  mov         rax,qword ptr [rbx+8]
00007FFF4A8B01D4  mov         r9d,3Eh
00007FFF4A8B01DA  cmp         r9,rax
00007FFF4A8B01DD  jae         00007FFF4A8B0245
00007FFF4A8B01DF  mov         r9d,3Fh
00007FFF4A8B01E5  cmp         r9,rcx
00007FFF4A8B01E8  jae         00007FFF4A8B0245
00007FFF4A8B01EA  mov         ecx,3Fh
00007FFF4A8B01EF  cmp         rcx,rax
00007FFF4A8B01F2  jae         00007FFF4A8B0245
00007FFF4A8B01F4  nop         word ptr [rax+rax]
00007FFF4A8B0200  movzx       ecx,byte ptr [rdi+rdx+10h]
00007FFF4A8B0205  movzx       eax,byte ptr [rbx+rdx+10h]
00007FFF4A8B020A  xor         ecx,eax
00007FFF4A8B020C  mov         byte ptr [rdi+rdx+10h],cl
00007FFF4A8B0210  movzx       ecx,byte ptr [rdi+rdx+11h]
00007FFF4A8B0215  movzx       eax,byte ptr [rbx+rdx+11h]
00007FFF4A8B021A  xor         ecx,eax
00007FFF4A8B021C  mov         byte ptr [rdi+rdx+11h],cl
00007FFF4A8B0220  add         rdx,2
                for (int p = 0; p < 64; p++)
00007FFF4A8B0224  cmp         rdx,40h
00007FFF4A8B0228  jl          00007FFF4A8B0200
+4
1

, . :

using System;

namespace SO30558357
{
    class Program
    {
        static void XorArray(byte[] a, byte[] b)
        {
            for (int p = 0; p< 64; p++)
                a[p] ^= b[p];
        }

        static void Main(string[] args)
        {
            byte[] a = new byte[64];
            byte[] b = new byte[64];
            Random r = new Random();

            r.NextBytes(a);
            r.NextBytes(b);

            XorArray(a, b);
            Console.ReadLine();  // when the program stops here
                                 // use Debug -> Attach to process
        }
    }
}

, Visual Studio 2013 Update 3, "Release Build" #, , CLR v4.0.30319. , , Roslyn, JIT, MSIL, .

x86 XorArray:

006F00D8  push        ebp  
006F00D9  mov         ebp,esp  
006F00DB  push        edi  
006F00DC  push        esi  
006F00DD  push        ebx  
006F00DE  push        eax  
006F00DF  mov         dword ptr [ebp-10h],edx  
006F00E2  xor         edi,edi  
006F00E4  mov         ebx,dword ptr [ecx+4]  
006F00E7  cmp         edi,ebx  
006F00E9  jae         006F010F  
006F00EB  lea         esi,[ecx+edi+8]  
006F00EF  movzx       eax,byte ptr [esi]  
006F00F2  mov         edx,dword ptr [ebp-10h]  
006F00F5  cmp         edi,dword ptr [edx+4]  
006F00F8  jae         006F010F  
006F00FA  movzx       edx,byte ptr [edx+edi+8]  
006F00FF  xor         eax,edx  
006F0101  mov         byte ptr [esi],al  
006F0103  inc         edi  
006F0104  cmp         edi,40h  
006F0107  jl          006F00E7  
006F0109  pop         ecx  
006F010A  pop         ebx  
006F010B  pop         esi  
006F010C  pop         edi  
006F010D  pop         ebp  
006F010E  ret

x64:

00007FFD4A3000FB  mov         rax,qword ptr [rsi+8]  
00007FFD4A3000FF  mov         rax,qword ptr [rbp+8]  
00007FFD4A300103  nop         word ptr [rax+rax]  
00007FFD4A300110  movzx       ecx,byte ptr [rsi+rdx+10h]  
00007FFD4A300115  movzx       eax,byte ptr [rdx+rbp+10h]  
00007FFD4A30011A  xor         ecx,eax  
00007FFD4A30011C  mov         byte ptr [rsi+rdx+10h],cl  
00007FFD4A300120  movzx       ecx,byte ptr [rsi+rdx+11h]  
00007FFD4A300125  movzx       eax,byte ptr [rdx+rbp+11h]  
00007FFD4A30012A  xor         ecx,eax  
00007FFD4A30012C  mov         byte ptr [rsi+rdx+11h],cl  
00007FFD4A300130  movzx       ecx,byte ptr [rsi+rdx+12h]  
00007FFD4A300135  movzx       eax,byte ptr [rdx+rbp+12h]  
00007FFD4A30013A  xor         ecx,eax  
00007FFD4A30013C  mov         byte ptr [rsi+rdx+12h],cl  
00007FFD4A300140  movzx       ecx,byte ptr [rsi+rdx+13h]  
00007FFD4A300145  movzx       eax,byte ptr [rdx+rbp+13h]  
00007FFD4A30014A  xor         ecx,eax  
00007FFD4A30014C  mov         byte ptr [rsi+rdx+13h],cl  
00007FFD4A300150  add         rdx,4  
00007FFD4A300154  cmp         rdx,40h  
00007FFD4A300158  jl          00007FFD4A300110

: x64 . - byte, 4 .

x86 , , .

- , .

, x86 :

00A000B1  xor         edi,edi  
00A000B3  mov         eax,dword ptr [ebp-10h]  
00A000B6  mov         ebx,dword ptr [eax+4]  
                a[p] ^= b[p];
00A000B9  mov         eax,dword ptr [ebp-10h]  
00A000BC  cmp         edi,ebx  
00A000BE  jae         00A000F5  
00A000C0  lea         esi,[eax+edi+8]  
00A000C4  movzx       eax,byte ptr [esi]  
00A000C7  mov         edx,dword ptr [ebp-14h]  
00A000CA  cmp         edi,dword ptr [edx+4]  
00A000CD  jae         00A000F5  
00A000CF  movzx       edx,byte ptr [edx+edi+8]  
00A000D4  xor         eax,edx  
00A000D6  mov         byte ptr [esi],al  
            for (int p = 0; p< 64; p++)
00A000D8  inc         edi  
00A000D9  cmp         edi,40h  
00A000DC  jl          00A000B9 

, , .

, x86 (EBX) , . "" - L1, , , , .

+5

All Articles