Skip to content

SequenceEqual is very slow on .NET Framework x86 #25501

@jkotas

Description

@jkotas

Performance regression introduced by change dotnet/corefx#28080.

A single call to SequenceEqual expands into 400 bytes of very inefficient code. .NET Framework x86 JIT is not able to optimize out the complex generic code.

If there is no way to make the type-specific optimizations work well, we should ifdef them out from the netstandard implementation. The portable System.Memory implementation will be slower, but it has to be fast enough to be usable on .NET Framework x86 because of it is likely going to be the most popular target for it.

04dd1351 8b7dd8          mov     edi,dword ptr [ebp-28h]
04dd1354 8d45cc          lea     eax,[ebp-34h]
04dd1357 8810            mov     byte ptr [eax],dl
04dd1359 b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd135e e88da4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd1363 8bf0            mov     esi,eax
04dd1365 b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd136a e881a4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd136f 3bc6            cmp     eax,esi
04dd1371 741a            je      test!My.Main()+0x125 (04dd138d)
04dd1373 b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd1378 e873a4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd137d 8bf0            mov     esi,eax
04dd137f b910b3a171      mov     ecx,offset mscorlib_ni+0x50b310 (71a1b310) (MT: System.SByte)
04dd1384 e867a4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd1389 3bc6            cmp     eax,esi
04dd138b 7511            jne     test!My.Main()+0x136 (04dd139e)
04dd138d c745c801000000  mov     dword ptr [ebp-38h],1
04dd1394 b801000000      mov     eax,1
04dd1399 e9ea000000      jmp     test!My.Main()+0x220 (04dd1488)
04dd139e b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd13a3 e848a4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd13a8 8bf0            mov     esi,eax
04dd13aa b93806a371      mov     ecx,offset mscorlib_ni+0x520638 (71a30638) (MT: System.Char)
04dd13af e83ca4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd13b4 3bc6            cmp     eax,esi
04dd13b6 7434            je      test!My.Main()+0x184 (04dd13ec)
04dd13b8 b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd13bd e82ea4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd13c2 8bf0            mov     esi,eax
04dd13c4 b96839a271      mov     ecx,offset mscorlib_ni+0x513968 (71a23968) (MT: System.Int16)
04dd13c9 e822a4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd13ce 3bc6            cmp     eax,esi
04dd13d0 741a            je      test!My.Main()+0x184 (04dd13ec)
04dd13d2 b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd13d7 e814a4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd13dc 8bf0            mov     esi,eax
04dd13de b9fc43a371      mov     ecx,offset mscorlib_ni+0x5243fc (71a343fc) (MT: System.UInt16)
04dd13e3 e808a4686e      call    clr!JIT_GetRuntimeType (7345b7f0)
>>> 04dd13e8 3bc6            cmp     eax,esi
04dd13ea 7511            jne     test!My.Main()+0x195 (04dd13fd)
04dd13ec c745c802000000  mov     dword ptr [ebp-38h],2
04dd13f3 b801000000      mov     eax,1
04dd13f8 e98b000000      jmp     test!My.Main()+0x220 (04dd1488)
04dd13fd b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd1402 e8e9a3686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd1407 8bf0            mov     esi,eax
04dd1409 b9901aa371      mov     ecx,offset mscorlib_ni+0x521a90 (71a31a90) (MT: System.Int32)
04dd140e e8dda3686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd1413 3bc6            cmp     eax,esi
04dd1415 741a            je      test!My.Main()+0x1c9 (04dd1431)
04dd1417 b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd141c e8cfa3686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd1421 8bf0            mov     esi,eax
04dd1423 b9e860a271      mov     ecx,offset mscorlib_ni+0x5160e8 (71a260e8) (MT: System.UInt32)
04dd1428 e8c3a3686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd142d 3bc6            cmp     eax,esi
04dd142f 750e            jne     test!My.Main()+0x1d7 (04dd143f)
04dd1431 c745c804000000  mov     dword ptr [ebp-38h],4
04dd1438 b801000000      mov     eax,1
04dd143d eb49            jmp     test!My.Main()+0x220 (04dd1488)
04dd143f b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd1444 e8a7a3686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd1449 8bf0            mov     esi,eax
04dd144b b95cb2a171      mov     ecx,offset mscorlib_ni+0x50b25c (71a1b25c) (MT: System.Int64)
04dd1450 e89ba3686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd1455 3bc6            cmp     eax,esi
04dd1457 741a            je      test!My.Main()+0x20b (04dd1473)
04dd1459 b9c010a371      mov     ecx,offset mscorlib_ni+0x5210c0 (71a310c0) (MT: System.Byte)
04dd145e e88da3686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd1463 8bf0            mov     esi,eax
04dd1465 b9700ba271      mov     ecx,offset mscorlib_ni+0x510b70 (71a20b70) (MT: System.UInt64)
04dd146a e881a3686e      call    clr!JIT_GetRuntimeType (7345b7f0)
04dd146f 3bc6            cmp     eax,esi
04dd1471 750e            jne     test!My.Main()+0x219 (04dd1481)
04dd1473 c745c808000000  mov     dword ptr [ebp-38h],8
04dd147a b801000000      mov     eax,1
04dd147f eb07            jmp     test!My.Main()+0x220 (04dd1488)
04dd1481 33d2            xor     edx,edx
04dd1483 8955c8          mov     dword ptr [ebp-38h],edx
04dd1486 33c0            xor     eax,eax
04dd1488 85c0            test    eax,eax
04dd148a 7441            je      test!My.Main()+0x265 (04dd14cd)
04dd148c 3b7dc4          cmp     edi,dword ptr [ebp-3Ch]
04dd148f 753a            jne     test!My.Main()+0x263 (04dd14cb)
04dd1491 8d45d0          lea     eax,[ebp-30h]
04dd1494 ff7008          push    dword ptr [eax+8]
04dd1497 ff7004          push    dword ptr [eax+4]
04dd149a ff30            push    dword ptr [eax]
04dd149c ff15e4950403    call    dword ptr ds:[30495E4h] (System.Runtime.InteropServices.MemoryMarshal.GetReference[[System.Byte, mscorlib]](System.Span`1<Byte>), mdToken: 06000168)
04dd14a2 8bf0            mov     esi,eax
04dd14a4 8d45bc          lea     eax,[ebp-44h]
04dd14a7 ff7008          push    dword ptr [eax+8]
04dd14aa ff7004          push    dword ptr [eax+4]
04dd14ad ff30            push    dword ptr [eax]
04dd14af ff154c960403    call    dword ptr ds:[304964Ch] (System.Runtime.InteropServices.MemoryMarshal.GetReference[[System.Byte, mscorlib]](System.ReadOnlySpan`1<Byte>), mdToken: 06000169)
04dd14b5 8bd0            mov     edx,eax
04dd14b7 8b45c8          mov     eax,dword ptr [ebp-38h]
04dd14ba 8945b8          mov     dword ptr [ebp-48h],eax
04dd14bd 0fafc7          imul    eax,edi
04dd14c0 50              push    eax
04dd14c1 8bce            mov     ecx,esi
04dd14c3 ff150c810403    call    dword ptr ds:[304810Ch] (System.SpanHelpers.SequenceEqual(Byte ByRef, Byte ByRef, System.NUInt), mdToken: 0600011a)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions