Skip to content

LSRA: Register spilling issue when using AsSpan and Slice causing slow performance #7809

Description

@ahsonkhan
public static Span<byte> TestAsSpan(int length)
{
    Stopwatch sw = new Stopwatch();
    var array = new byte[length];
    int halfLength = length / 2;
    Span<byte> span;
    sw.Restart();
    for (int i = 0; i < BaseIterations; i++)
    {
        span = array.AsSpan().Slice(halfLength, 10);
    }
    sw.Stop();
    var time = sw.ElapsedMilliseconds;
    Console.WriteLine(time + " : " + span.Length);
    return span;
}

public static Span<byte> TestSliceAsSpan(int length)
{
    Stopwatch sw = new Stopwatch();
    var array = new byte[length];
    int halfLength = length / 2;
    Span<byte> span;
    sw.Restart();
    for (int i = 0; i < BaseIterations; i++)
    {
        span = array.SliceAsSpan(halfLength, 10);
    }
    sw.Stop();
    var time = sw.ElapsedMilliseconds;
    Console.WriteLine(time + " : " + span.Length);
    return span;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T>(this T[] array)
{
    return new Span<T>(array);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> SliceAsSpan<T>(this T[] array, int index, int length)
{
    return new Span<T>(array, index, length);
}

Runtime:
AsSpan().Slice() - 1094 ms (approximately 30% slower)
SliceAsSpan() - 827 ms

            span = array.AsSpan().Slice(halfLength, 10);

00007FFCB39B24F9 lea rax,[rbp+10h]
00007FFCB39B24FD mov qword ptr [rsp+30h],rax
00007FFCB39B2502 mov eax,dword ptr [rbp+8]
00007FFCB39B2505 mov rdx,qword ptr [rsp+30h]
00007FFCB39B250A cmp edi,eax
00007FFCB39B250C ja 00007FFCB39B25C8
00007FFCB39B2512 sub eax,edi
00007FFCB39B2514 cmp eax,0Ah
00007FFCB39B2517 jb 00007FFCB39B25C8
00007FFCB39B251D movsxd rax,edi
00007FFCB39B2520 add rax,rdx
00007FFCB39B2523 mov qword ptr [rsp+28h],rax
00007FFCB39B2528 mov r14d,0Ah
00007FFCB39B252E mov r15,qword ptr [rsp+28h]

            span = array.SliceAsSpan(halfLength, 10);

00007FFCB39B2C85 mov eax,dword ptr [rbp+8]
00007FFCB39B2C88 cmp eax,edi
00007FFCB39B2C8A jb 00007FFCB39B2D4A
00007FFCB39B2C90 sub eax,edi
00007FFCB39B2C92 cmp eax,0Ah
00007FFCB39B2C95 jb 00007FFCB39B2D4A
00007FFCB39B2C9B lea rax,[rbp+10h]
00007FFCB39B2C9F movsxd rdx,edi
00007FFCB39B2CA2 add rax,rdx
00007FFCB39B2CA5 mov qword ptr [rsp+20h],rax
00007FFCB39B2CAA mov r14d,0Ah
00007FFCB39B2CB0 mov r15,qword ptr [rsp+20h]

From: https://github.com/dotnet/corefx/issues/17414#issuecomment-290182549

They show different register allocation. Minor deficiency in the JIT optimizations.
category:cq
theme:register-allocator
skill-level:expert
cost:medium

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIenhancementProduct code improvement that does NOT require public API changes/additionsneeds-further-triageIssue has been initially triaged, but needs deeper consideration or reconsiderationoptimizationtenet-performancePerformance related issue

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions