dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.27k stars 4.73k forks source link

Microbenchmarks where inliner runs out of budget with TieredPGO #85531

Open AndyAyersMS opened 1 year ago

AndyAyersMS commented 1 year ago

See https://github.com/dotnet/runtime/issues/84264 for context

A number of microbenchmarks—particularly those under System.Text.Json—run out of budget when run with TieredPGO.

Suggest that we review RWC/SPMI to see how often this thing comes up outside of microbenchmarks.

Possible fixes

ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.

Issue Details
See https://github.com/dotnet/runtime/issues/84264 for context A number of microbenchmarks—particularly those under `System.Text.Json`—run out of budget when run with TieredPGO. * [System.Text.Json.Tests.Perf_Get.GetByte](https://github.com/dotnet/runtime/issues/84264#issuecomment-1501985127) and related * [System.Text.Json.Serialization.Tests.WriteJson<ImmutableDictionary<String, String>>.SerializeToWriter(Mode: SourceGen)](https://github.com/dotnet/runtime/issues/84264#issuecomment-1504465247) Suggest that we review RWC/SPMI to see how often this thing comes up outside of microbenchmarks. Possible fixes * increase budget (if these cases are rare) * reduce amount of `AggressiveInlining` in `System.Text.Json` (if these cases are all json related) * rework inliner to consider candidates in priority order
Author: AndyAyersMS
Assignees: -
Labels: `area-System.Text.Json`
Milestone: -
AndyAyersMS commented 1 year ago

cc @EgorBo

MichalPetryka commented 1 year ago

While looking at dumps for #85349 I've noticed that a lot of autoproperties weren't inlined in System.Text.Json, would it make sense to always inline really small methods like autoproperties and maybe not count them into the inliner budget?

AndyAyersMS commented 1 year ago

While looking at dumps for #85349 I've noticed that a lot of autoproperties weren't inlined in System.Text.Json, would it make sense to always inline really small methods like autoproperties and maybe not count them into the inliner budget?

Can you give a more specific example?

Really small methods should already be bypassing budget checks.

MichalPetryka commented 1 year ago

Can you give a more specific example?

Here, note all the set_ calls. Since that PR let the jit inline more, a few of those were inlined and turned into a single mov like this: image

AndyAyersMS commented 1 year ago

These look small in C#, but can you verify they're small in IL?

MichalPetryka commented 1 year ago

These look small in C#, but can you verify they're small in IL?

Well they're autoproperties, won't those be always compiled as ldarg.0+ldfld/ldarg.0+ldarg.1+stfld?

AndyAyersMS commented 1 year ago

These look small in C#, but can you verify they're small in IL?

Well they're autoproperties, won't those be always compiled as ldarg.0+ldfld/ldarg.0+ldarg.1+stfld?

I don't know about always, but it looks like these are indeed small:

.method public hidebysig specialname instance void modreq([System.Runtime]System.Runtime.CompilerServices.IsExternalInit) 
        set_IsPublic(bool 'value') cil managed
{
  .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       8 (0x8)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldarg.1
  IL_0002:  stfld      bool class System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues`1<!T>::'<IsPublic>k__BackingField'
  IL_0007:  ret
} // end of method JsonPropertyInfoValues`1::set_IsPublic

Now, do you know for sure why these didn't get inlined?

EgorBo commented 1 year ago

I guess when we run out of budget (or too many locals?) we give up even on "below ALWAYS_INLINE" stuff

MichalPetryka commented 1 year ago

Now, do you know for sure why these didn't get inlined?

I haven't checked thoroughly, but the change from the PR made the assignments to delegate typed properties take less of the budget, so that's why I assume it's more budget being available that let it inline more.

AndyAyersMS commented 1 year ago

Now, do you know for sure why these didn't get inlined?

I haven't checked thoroughly, but the change from the PR made the assignments to delegate typed properties take less of the budget, so that's why I assume it's more budget being available that let it inline more.

I think it's more likely that we hit the local var limit, and since your change creates fewer local vars, we can inline more.

The only way to know for sure is to look at the jit dump or at least the inline summary tree.

EgorBo commented 1 year ago

Call graph for GetByte benchmark:

Inlines into Program+Perf_Get:GetByte():ubyte:this:
  [INLINED: below ALWAYS_INLINE size] System.ReadOnlySpan`1[ubyte]:op_Implicit(ubyte[]):System.ReadOnlySpan`1[ubyte]
    [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ubyte[]):this
  [INLINED: below ALWAYS_INLINE size] System.Text.Json.Utf8JsonReader:.ctor(System.ReadOnlySpan`1[ubyte],System.Text.Json.JsonReaderOptions):this
    [INLINED: profitable inline] System.Text.Json.JsonReaderState:.ctor(System.Text.Json.JsonReaderOptions):this
    [FAILED: too many il bytes] System.Text.Json.Utf8JsonReader:.ctor(System.ReadOnlySpan`1[ubyte],bool,System.Text.Json.JsonReaderState):this
  [INLINED: profitable inline] System.Text.Json.Utf8JsonReader:Read():bool:this
    [INLINED: profitable inline] System.Text.Json.Utf8JsonReader:ReadSingleSegment():bool:this
      [INLINED: below ALWAYS_INLINE size] System.Text.Json.Utf8JsonReader:set_ValueSpan(System.ReadOnlySpan`1[ubyte]):this
      [INLINED: below ALWAYS_INLINE size] System.Text.Json.Utf8JsonReader:set_ValueIsEscaped(bool):this
      [INLINED: aggressive inline attribute] System.Text.Json.Utf8JsonReader:HasMoreData():bool:this
        [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:get_IsLastSpan():bool:this
        [INLINED: below ALWAYS_INLINE size] System.Text.Json.BitStack:get_CurrentDepth():int:this
        [FAILED: does not return] System.Text.Json.ThrowHelper:ThrowJsonReaderException(byref,int,ubyte,System.ReadOnlySpan`1[ubyte])
        [INLINED: below ALWAYS_INLINE size] System.Text.Json.JsonReaderOptions:get_CommentHandling():ubyte:this
        [FAILED: does not return] System.Text.Json.ThrowHelper:ThrowJsonReaderException(byref,int,ubyte,System.ReadOnlySpan`1[ubyte])
      [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:SkipWhiteSpace():this
      [INLINED: aggressive inline attribute] System.Text.Json.Utf8JsonReader:HasMoreData():bool:this
        [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:get_IsLastSpan():bool:this
        [INLINED: below ALWAYS_INLINE size] System.Text.Json.BitStack:get_CurrentDepth():int:this
        [FAILED: does not return] System.Text.Json.ThrowHelper:ThrowJsonReaderException(byref,int,ubyte,System.ReadOnlySpan`1[ubyte])
        [INLINED: below ALWAYS_INLINE size] System.Text.Json.JsonReaderOptions:get_CommentHandling():ubyte:this
        [FAILED: does not return] System.Text.Json.ThrowHelper:ThrowJsonReaderException(byref,int,ubyte,System.ReadOnlySpan`1[ubyte])
      [INLINED: below ALWAYS_INLINE size] System.Text.Json.Utf8JsonReader:set_TokenStartIndex(long):this
      [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:ConsumeNextTokenOrRollback(ubyte):bool:this
      [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:EndObject():this
      [FAILED: does not return] System.Text.Json.ThrowHelper:ThrowJsonReaderException(byref,int,ubyte,System.ReadOnlySpan`1[ubyte])
      [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:ConsumePropertyName():bool:this
      [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:EndArray():this
      [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:ConsumeValue(ubyte):bool:this
      [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:ConsumeValue(ubyte):bool:this
      [FAILED: unprofitable inline] System.Text.Json.Utf8JsonReader:ConsumeNextTokenOrRollback(ubyte):bool:this
      [INLINED: profitable inline] System.Text.Json.Utf8JsonReader:ReadFirstToken(ubyte):bool:this
        [INLINED: profitable inline] System.Text.Json.BitStack:SetFirstBit():this
        [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:Slice(int,int):System.ReadOnlySpan`1[ubyte]:this
          [FAILED: does not return] System.ThrowHelper:ThrowArgumentOutOfRangeException()
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(byref,int):this
            [FAILED: unprofitable inline] System.Diagnostics.Debug:Assert(bool)
        [INLINED: below ALWAYS_INLINE size] System.Text.Json.Utf8JsonReader:set_ValueSpan(System.ReadOnlySpan`1[ubyte]):this
        [INLINED: profitable inline] System.Text.Json.BitStack:ResetFirstBit():this
        [FAILED: inline exceeds budget] System.ReadOnlySpan`1[ubyte]:Slice(int,int):System.ReadOnlySpan`1[ubyte]:this
        [INLINED: below ALWAYS_INLINE size] System.Text.Json.Utf8JsonReader:set_ValueSpan(System.ReadOnlySpan`1[ubyte]):this
        [INLINED: below ALWAYS_INLINE size] System.Text.Json.JsonHelpers:IsDigit(ubyte):bool
        [FAILED: inline exceeds budget] System.ReadOnlySpan`1[ubyte]:Slice(int):System.ReadOnlySpan`1[ubyte]:this
        [FAILED: inline exceeds budget] System.Text.Json.Utf8JsonReader:TryGetNumber(System.ReadOnlySpan`1[ubyte],byref):bool:this
        [FAILED: inline exceeds budget] System.Text.Json.Utf8JsonReader:ConsumeValue(ubyte):bool:this
    [FAILED: inline exceeds budget] System.Text.Json.Utf8JsonReader:ReadMultiSegment():bool:this
    [INLINED: below ALWAYS_INLINE size] System.Text.Json.Utf8JsonReader:get_TokenType():ubyte:this
    [FAILED: does not return] System.Text.Json.ThrowHelper:ThrowJsonReaderException(byref,int,ubyte,System.ReadOnlySpan`1[ubyte])
  [INLINED: profitable inline] System.Text.Json.Utf8JsonReader:GetByte():ubyte:this
    [INLINED: profitable inline] System.Text.Json.Utf8JsonReader:TryGetByte(byref):bool:this
      [FAILED: inline exceeds budget] System.Text.Json.Utf8JsonReader:get_TokenType():ubyte:this
      [FAILED: inline exceeds budget] System.Text.Json.Utf8JsonReader:get_TokenType():ubyte:this
      [FAILED: inline exceeds budget] System.Text.Json.ThrowHelper:ThrowInvalidOperationException_ExpectedNumber(ubyte)
      [FAILED: inline exceeds budget] System.Text.Json.Utf8JsonReader:get_HasValueSequence():bool:this
      [FAILED: inline exceeds budget] System.Text.Json.Utf8JsonReader:get_ValueSpan():System.ReadOnlySpan`1[ubyte]:this
      [FAILED: inline exceeds budget] System.Text.Json.Utf8JsonReader:get_ValueSequence():System.Buffers.ReadOnlySequence`1[ubyte]:this
      [FAILED: inline exceeds budget] System.Buffers.BuffersExtensions:ToArray[ubyte](byref):ubyte[]
      [FAILED: inline exceeds budget] System.ReadOnlySpan`1[ubyte]:op_Implicit(ubyte[]):System.ReadOnlySpan`1[ubyte]
      [FAILED: inline exceeds budget] System.Text.Json.Utf8JsonReader:TryGetByteCore(byref,System.ReadOnlySpan`1[ubyte]):bool
    [FAILED: inline exceeds budget] System.Text.Json.ThrowHelper:ThrowFormatException(int)
EgorBo commented 1 year ago

Tested the 1P web service we usually test:

Default mode: 40 "exceeds budget" decisions, among them in BCL:

System.Reflection.RuntimeAssembly:GetType(System.String,bool,bool)
System.Type:GetType(System.String)
System.Type:GetType(System.String)
System.Reflection.TypeNameParser:GetType(System.String,System.Reflection.Assembly,bool,bool)
System.Enum:TryParse[int](System.String,byref)

(these are root methods where some of their inlinees refused to inlined due to the budge thing)

PGO=1: 2350 "exceeds budget" decisions or ~60X more than in the no-PGO mode.

I tried to play with various knobs, e.g. limitted the max IL size for PGO mode (it helped but still a lot), tried to play with various benefit multipliers trying to add additional friction for inlining in big methods (or of big inlinees) - didn't help.

The only simple thing we can do is just to bump the budget now, proper changes definitely require a lot of re-thinking E.g. this change: https://github.com/EgorBo/runtime-1/commit/bb4deca3ded19a69492b1fb09edc7e602c90a7b3 reduced number of "exceeds budget" decisions to 202 (5X more than non-PGO mode instead of 60X).

I changed EstimateRootTime to return a fixed constant because we used calculate our time budget based on current root's method size. Also, slightly decreased the estimated time budget for callees.

Tested a couple of apps and didn't notice startup regressions from this change.

UPD: I probably overdramatized the numbers, once we hit an "exceed budget" problem we start label all callees with it in the current root, even those we would never inline anyway. So the real number of inlinees we should have inlined but we didn't is way lower.

cc @AndyAyersMS

EgorBo commented 1 year ago

https://github.com/dotnet/runtime/pull/85322 @stephentoub e.g. this change seems to regressed guid parsing with PGO. A rarely taken path (I assume we can say that for the hex guid format) was marked as always inline: Actually, I might be wrong, I don't see HexsToChars here. But still, Guid parsing hits the problem too:

Inlines into System.Guid:TryParseGuid(System.ReadOnlySpan`1[ushort],byref):bool:
  [INLINED: aggressive inline attribute] System.MemoryExtensions:Trim(System.ReadOnlySpan`1[ushort]):System.ReadOnlySpan`1[ushort]
    [INLINED: profitable inline] System.Char:IsWhiteSpace(ushort):bool
      [INLINED: profitable inline] System.Char:IsLatin1(ushort):bool
        [INLINED: below ALWAYS_INLINE size] System.Char:get_Latin1CharInfo():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
      [INLINED: profitable inline] System.Char:IsWhiteSpaceLatin1(ushort):bool
        [INLINED: profitable inline] System.Char:IsLatin1(ushort):bool
          [INLINED: below ALWAYS_INLINE size] System.Char:get_Latin1CharInfo():System.ReadOnlySpan`1[ubyte]
            [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
              [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
              [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [INLINED: profitable inline] System.Diagnostics.Debug:Assert(bool)
          [INLINED: below ALWAYS_INLINE size] System.Diagnostics.Debug:Assert(bool,System.String,System.String)
            [FAILED: noinline per IL/cached result] System.Diagnostics.Debug:Fail(System.String,System.String)
        [INLINED: below ALWAYS_INLINE size] System.Char:get_Latin1CharInfo():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
      [FAILED: unprofitable inline] System.Globalization.CharUnicodeInfo:GetIsWhiteSpace(ushort):bool
    [INLINED: profitable inline] System.Char:IsWhiteSpace(ushort):bool
      [INLINED: profitable inline] System.Char:IsLatin1(ushort):bool
        [INLINED: below ALWAYS_INLINE size] System.Char:get_Latin1CharInfo():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
      [INLINED: profitable inline] System.Char:IsWhiteSpaceLatin1(ushort):bool
        [INLINED: profitable inline] System.Char:IsLatin1(ushort):bool
          [INLINED: below ALWAYS_INLINE size] System.Char:get_Latin1CharInfo():System.ReadOnlySpan`1[ubyte]
            [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
              [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
              [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [INLINED: profitable inline] System.Diagnostics.Debug:Assert(bool)
          [INLINED: below ALWAYS_INLINE size] System.Diagnostics.Debug:Assert(bool,System.String,System.String)
            [FAILED: noinline per IL/cached result] System.Diagnostics.Debug:Fail(System.String,System.String)
        [INLINED: below ALWAYS_INLINE size] System.Char:get_Latin1CharInfo():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
      [FAILED: unprofitable inline] System.Globalization.CharUnicodeInfo:GetIsWhiteSpace(ushort):bool
    [FAILED: noinline per IL/cached result] System.MemoryExtensions:<Trim>g__TrimFallback|194_0(System.ReadOnlySpan`1[ushort]):System.ReadOnlySpan`1[ushort]
  [FAILED: unprofitable inline] System.Guid+GuidResult:SetFailure(int):this
  [FAILED: unprofitable inline] System.Guid:TryParseExactP(System.ReadOnlySpan`1[ushort],byref):bool
  [FAILED: unprofitable inline] System.Guid:TryParseExactX(System.ReadOnlySpan`1[ushort],byref):bool
  [INLINED: profitable inline] System.Guid:TryParseExactB(System.ReadOnlySpan`1[ushort],byref):bool
    [FAILED: unprofitable inline] System.Guid+GuidResult:SetFailure(int):this
    [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ushort]:Slice(int,int):System.ReadOnlySpan`1[ushort]:this
      [FAILED: does not return] System.ThrowHelper:ThrowArgumentOutOfRangeException()
      [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ushort]:.ctor(byref,int):this
        [INLINED: profitable inline] System.Diagnostics.Debug:Assert(bool)
          [INLINED: below ALWAYS_INLINE size] System.Diagnostics.Debug:Assert(bool,System.String,System.String)
    [INLINED: profitable inline] System.Guid:TryParseExactD(System.ReadOnlySpan`1[ushort],byref):bool
      [FAILED: unprofitable inline] System.Guid+GuidResult:SetFailure(int):this
      [INLINED: aggressive inline attribute] System.Span`1[System.Guid+GuidResult]:.ctor(byref):this
      [INLINED: aggressive inline attribute] System.Runtime.InteropServices.MemoryMarshal:AsBytes[System.Guid+GuidResult](System.Span`1[System.Guid+GuidResult]):System.Span`1[ubyte]
        [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[System.Guid+GuidResult]():bool
        [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[System.Guid+GuidResult](System.Span`1[System.Guid+GuidResult]):byref
        [INLINED: aggressive inline attribute] System.Span`1[ubyte]:.ctor(byref,int):this
          [INLINED: profitable inline] System.Diagnostics.Debug:Assert(bool)
            [INLINED: below ALWAYS_INLINE size] System.Diagnostics.Debug:Assert(bool,System.String,System.String)
              [FAILED: noinline per IL/cached result] System.Diagnostics.Debug:Fail(System.String,System.String)
      [INLINED: aggressive inline attribute] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
        [INLINED: below ALWAYS_INLINE size] System.HexConverter:get_CharToHexLookup():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
      [INLINED: aggressive inline attribute] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
        [INLINED: below ALWAYS_INLINE size] System.HexConverter:get_CharToHexLookup():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
      [INLINED: aggressive inline attribute] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
        [INLINED: below ALWAYS_INLINE size] System.HexConverter:get_CharToHexLookup():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
      [INLINED: aggressive inline attribute] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
        [INLINED: below ALWAYS_INLINE size] System.HexConverter:get_CharToHexLookup():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
      [INLINED: aggressive inline attribute] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
        [INLINED: below ALWAYS_INLINE size] System.HexConverter:get_CharToHexLookup():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
      [INLINED: aggressive inline attribute] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
        [INLINED: below ALWAYS_INLINE size] System.HexConverter:get_CharToHexLookup():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [INLINED: below ALWAYS_INLINE size] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: unprofitable inline] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
        [INLINED: below ALWAYS_INLINE size] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
      [INLINED: aggressive inline attribute] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
        [INLINED: below ALWAYS_INLINE size] System.HexConverter:get_CharToHexLookup():System.ReadOnlySpan`1[ubyte]
          [INLINED: aggressive inline attribute] System.ReadOnlySpan`1[ubyte]:.ctor(ulong,int):this
            [FAILED: inline exceeds budget] System.Runtime.CompilerServices.RuntimeHelpers:IsReferenceOrContainsReferences[ubyte]():bool
            [FAILED: inline exceeds budget] System.ThrowHelper:ThrowInvalidTypeWithPointersNotSupported(System.Type)
        [FAILED: inline exceeds budget] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
        [FAILED: inline exceeds budget] System.Runtime.InteropServices.MemoryMarshal:GetReference[ubyte](System.ReadOnlySpan`1[ubyte]):byref
      [FAILED: inline exceeds budget] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
      [FAILED: inline exceeds budget] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
      [FAILED: inline exceeds budget] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
      [FAILED: inline exceeds budget] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
      [FAILED: inline exceeds budget] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
      [FAILED: inline exceeds budget] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
      [FAILED: inline exceeds budget] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
      [FAILED: inline exceeds budget] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
      [FAILED: inline exceeds budget] System.Guid:DecodeByte(ulong,ulong,byref):ubyte
      [FAILED: inline exceeds budget] System.MemoryExtensions:IndexOfAny[ushort](System.ReadOnlySpan`1[ushort],ushort,ushort,ushort):int
      [FAILED: inline exceeds budget] System.Guid:<TryParseExactD>g__TryCompatParsing|31_0(System.ReadOnlySpan`1[ushort],byref):bool
      [FAILED: inline exceeds budget] System.Guid+GuidResult:SetFailure(int):this
  [FAILED: inline exceeds budget] System.Guid:TryParseExactN(System.ReadOnlySpan`1[ushort],byref):bool
  [FAILED: inline exceeds budget] System.Guid:TryParseExactD(System.ReadOnlySpan`1[ushort],byref):bool
EgorBo commented 1 year ago

One thing I noticed that methods with [Intrinsic] and a default implementation (in case if intrinsic is not expanded) may eat budget as well despite being imported as intrinsic.

EgorBo commented 1 year ago

Moving to 9.0 as it's probably too late to land invasive changes for this

EgorBo commented 3 months ago

Moving to 10.0 since any changes here potentially have too risky impact