Skip to content

Consider hand-written JIT helpers for more platforms or use portable version everywhere #67776

@AaronRobinsonMSFT

Description

@AaronRobinsonMSFT

There are some JIT helpers that are hand-written assembly but are only available on Windows-x64. The impact of these helpers can be profound, which means we might be missing benefits on non-Windows-x64 platforms.

JIT helpers as assembly with fallbacks into the VM (C++), Windows-x64 only.

Method Mean Error StdDev
CORINFO_HELP_NEWSFAST 1.865 ns 0.0356 ns 0.0333 ns
CORINFO_HELP_BOX 4.234 ns 0.0396 ns 0.0351 ns
CORINFO_HELP_NEWARR_1_VC 17.932 ns 0.0935 ns 0.0781 ns
CORINFO_HELP_NEWARR_1_OBJ 9.989 ns 0.2062 ns 0.1828 ns

JIT helpers (portable) calling into the VM (C++), non-Windows platforms. Note there is no BOX portable version.

Method Mean Error StdDev
CORINFO_HELP_NEWSFAST 2.136 ns 0.0269 ns 0.0238 ns
CORINFO_HELP_NEWARR_1_VC 17.999 ns 0.2288 ns 0.2028 ns
CORINFO_HELP_NEWARR_1_OBJ 10.001 ns 0.1342 ns 0.1190 ns

JIT helpers in the VM (C++). Collected on Windows-x64 for relative performance impact.

Method Mean Error StdDev
CORINFO_HELP_NEWSFAST 12.84 ns 0.309 ns 0.402 ns
CORINFO_HELP_BOX 15.50 ns 0.316 ns 0.363 ns
CORINFO_HELP_NEWARR_1_VC 30.37 ns 0.243 ns 0.190 ns
CORINFO_HELP_NEWARR_1_OBJ 23.83 ns 0.262 ns 0.219 ns

It could be possible to write the JIT helpers with new intrinsics as IL instead of assembly on all the platforms.

See the dynamic update for JIT helper:

SetJitHelperFunction(CORINFO_HELP_NEWSFAST, JIT_TrialAllocSFastMP_InlineGetThread);
SetJitHelperFunction(CORINFO_HELP_NEWSFAST_ALIGN8, JIT_TrialAllocSFastMP_InlineGetThread);
SetJitHelperFunction(CORINFO_HELP_BOX, JIT_BoxFastMP_InlineGetThread);
SetJitHelperFunction(CORINFO_HELP_NEWARR_1_VC, JIT_NewArr1VC_MP_InlineGetThread);
SetJitHelperFunction(CORINFO_HELP_NEWARR_1_OBJ, JIT_NewArr1OBJ_MP_InlineGetThread);

using System;
using System.Security.Cryptography;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

class Program
{
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<JITHelpers>(args: args);
    }
}

public struct VC
{
    public int A;
    public float B;
    public object C;
}

public class C
{
    public int A;
}

public class JITHelpers
{
    private VC _vc;

    public JITHelpers()
    {
        _vc = new VC() { A = 10, B = .1f, C = this };
    }

    [Benchmark]
    public C CORINFO_HELP_NEWSFAST() => new C();

    [Benchmark]
    public object CORINFO_HELP_BOX() => (object)_vc;

    [Benchmark]
    public VC[] CORINFO_HELP_NEWARR_1_VC() => new VC[32];

    [Benchmark]
    public C[] CORINFO_HELP_NEWARR_1_OBJ() => new C[32];
}

/cc @davidwrighton

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions