Int32.ToString() performance improvements in .NET 8




Date Added (UTC):

15 Apr 2024 @ 19:30

Date Updated (UTC):

15 Apr 2024 @ 19:30


.NET Version(s):

.NET 7 .NET 8

Tag(s):

#.Net8PerfImprovement


Added By:
Profile Image

Blog   
Ireland    
.NET Developer and tech lead from Ireland!

Benchmark Results:





Benchmark Code:



using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Reports;

[HideColumns("Error", "StdDev", "Median", "RatioSD")]
[MemoryDiagnoser(displayGenColumns: false)]
[Config(typeof(Config))]
public class IntToString
{
    [Benchmark]
    [Arguments(12)]
    [Arguments(123)]
    [Arguments(1_234_567_890)]
    public string Int32ToString(int i) => i.ToString();

    private class Config : ManualConfig
    {
        public Config()
        {
            AddJob(Job.Default.WithId(".NET 7").WithRuntime(CoreRuntime.Core70).AsBaseline());
            AddJob(Job.Default.WithId(".NET 8").WithRuntime(CoreRuntime.Core80));

            SummaryStyle =
                SummaryStyle.Default.WithRatioStyle(RatioStyle.Percentage);
        }
    }
}

// .NET 7, .NET 8
public string Int32ToString(int i)
{
    return i.ToString();
}

// .NET 7
.assembly _
{
    .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = (
        01 00 08 00 00 00 00 00
    )
    .custom instance void [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = (
        01 00 01 00 54 02 16 57 72 61 70 4e 6f 6e 45 78
        63 65 70 74 69 6f 6e 54 68 72 6f 77 73 01
    )
    .custom instance void [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (
        01 00 02 00 00 00 00 00
    )
    .permissionset reqmin = (
        2e 01 80 8a 53 79 73 74 65 6d 2e 53 65 63 75 72
        69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e
        53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69
        6f 6e 41 74 74 72 69 62 75 74 65 2c 20 53 79 73
        74 65 6d 2e 52 75 6e 74 69 6d 65 2c 20 56 65 72
        73 69 6f 6e 3d 37 2e 30 2e 30 2e 30 2c 20 43 75
        6c 74 75 72 65 3d 6e 65 75 74 72 61 6c 2c 20 50
        75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e 3d 62 30
        33 66 35 66 37 66 31 31 64 35 30 61 33 61 15 01
        54 02 10 53 6b 69 70 56 65 72 69 66 69 63 61 74
        69 6f 6e 01
    )
    .hash algorithm 0x00008004 // SHA1
    .ver 0:0:0:0
}

.class private auto ansi '<Module>'
{
} // end of class <Module>

.class public auto ansi beforefieldinit IntToString
    extends [System.Runtime]System.Object
{
    .custom instance void [BenchmarkDotNet]BenchmarkDotNet.Attributes.HideColumnsAttribute::.ctor(string[]) = (
        01 00 04 00 00 00 05 45 72 72 6f 72 06 53 74 64
        44 65 76 06 4d 65 64 69 61 6e 07 52 61 74 69 6f
        53 44 00 00
    )
    .custom instance void [BenchmarkDotNet]BenchmarkDotNet.Attributes.MemoryDiagnoserAttribute::.ctor(bool) = (
        01 00 00 00 00
    )
    .custom instance void [BenchmarkDotNet]BenchmarkDotNet.Attributes.ConfigAttribute::.ctor(class [System.Runtime]System.Type) = (
        01 00 12 49 6e 74 54 6f 53 74 72 69 6e 67 2b 43
        6f 6e 66 69 67 00 00
    )
    // Nested Types
    .class nested private auto ansi beforefieldinit Config
        extends [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig
    {
        // Methods
        .method public hidebysig specialname rtspecialname 
            instance void .ctor () cil managed 
        {
            // Method begins at RVA 0x20b0
            // Code size 111 (0x6f)
            .maxstack 6

            // sequence point: (line 32, col 9) to (line 32, col 24) in _
            IL_0000: ldarg.0
            IL_0001: call instance void [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig::.ctor()
            // sequence point: (line 34, col 13) to (line 34, col 95) in _
            IL_0006: ldarg.0
            IL_0007: ldc.i4.1
            IL_0008: newarr [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job
            IL_000d: dup
            IL_000e: ldc.i4.0
            IL_000f: ldsfld !0 class [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobMode`1<class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job>::Default
            IL_0014: ldstr ".NET 7"
            IL_0019: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::WithId(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job, string)
            IL_001e: ldsfld class [BenchmarkDotNet]BenchmarkDotNet.Environments.CoreRuntime [BenchmarkDotNet]BenchmarkDotNet.Environments.CoreRuntime::Core70
            IL_0023: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::WithRuntime(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job, class [BenchmarkDotNet]BenchmarkDotNet.Environments.Runtime)
            IL_0028: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::AsBaseline(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job)
            IL_002d: stelem.ref
            IL_002e: call instance class [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig::AddJob(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job[])
            IL_0033: pop
            // sequence point: (line 35, col 13) to (line 35, col 82) in _
            IL_0034: ldarg.0
            IL_0035: ldc.i4.1
            IL_0036: newarr [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job
            IL_003b: dup
            IL_003c: ldc.i4.0
            IL_003d: ldsfld !0 class [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobMode`1<class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job>::Default
            IL_0042: ldstr ".NET 8"
            IL_0047: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::WithId(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job, string)
            IL_004c: ldsfld class [BenchmarkDotNet]BenchmarkDotNet.Environments.CoreRuntime [BenchmarkDotNet]BenchmarkDotNet.Environments.CoreRuntime::Core80
            IL_0051: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::WithRuntime(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job, class [BenchmarkDotNet]BenchmarkDotNet.Environments.Runtime)
            IL_0056: stelem.ref
            IL_0057: call instance class [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig::AddJob(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job[])
            IL_005c: pop
            // sequence point: (line 37, col 13) to (line 38, col 76) in _
            IL_005d: ldarg.0
            IL_005e: ldsfld class [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle::Default
            IL_0063: ldc.i4.1
            IL_0064: callvirt instance class [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle::WithRatioStyle(valuetype [BenchmarkDotNet]BenchmarkDotNet.Columns.RatioStyle)
            IL_0069: call instance void [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig::set_SummaryStyle(class [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle)
            // sequence point: (line 39, col 9) to (line 39, col 10) in _
            IL_006e: ret
        } // end of method Config::.ctor

    } // end of class Config


    // Methods
    .method public hidebysig 
        instance string Int32ToString (
            int32 i
        ) cil managed 
    {
        .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
            01 00 01 00 00
        )
        .custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.BenchmarkAttribute::.ctor(int32, string) = (
            01 00 18 00 00 00 01 5f 00 00
        )
        .custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.ArgumentsAttribute::.ctor(object[]) = (
            01 00 01 00 00 00 08 0c 00 00 00 00 00
        )
        .custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.ArgumentsAttribute::.ctor(object[]) = (
            01 00 01 00 00 00 08 7b 00 00 00 00 00
        )
        .custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.ArgumentsAttribute::.ctor(object[]) = (
            01 00 01 00 00 00 08 d2 02 96 49 00 00
        )
        // Method begins at RVA 0x209d
        // Code size 8 (0x8)
        .maxstack 8

        // sequence point: (line 28, col 43) to (line 28, col 55) in _
        IL_0000: ldarga.s i
        IL_0002: call instance string [System.Runtime]System.Int32::ToString()
        IL_0007: ret
    } // end of method IntToString::Int32ToString

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x20a6
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Runtime]System.Object::.ctor()
        IL_0006: ret
    } // end of method IntToString::.ctor

} // end of class IntToString

.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute
    extends [System.Runtime]System.Attribute
{
    .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = (
        01 00 00 00
    )
    // Methods
    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Runtime]System.Attribute::.ctor()
        IL_0006: ret
    } // end of method EmbeddedAttribute::.ctor

} // end of class Microsoft.CodeAnalysis.EmbeddedAttribute

.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.NullableAttribute
    extends [System.Runtime]System.Attribute
{
    .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void [System.Runtime]System.AttributeUsageAttribute::.ctor(valuetype [System.Runtime]System.AttributeTargets) = (
        01 00 84 6b 00 00 02 00 54 02 0d 41 6c 6c 6f 77
        4d 75 6c 74 69 70 6c 65 00 54 02 09 49 6e 68 65
        72 69 74 65 64 00
    )
    // Fields
    .field public initonly uint8[] NullableFlags

    // Methods
    .method public hidebysig specialname rtspecialname 
        instance void .ctor (
            uint8 ''
        ) cil managed 
    {
        // Method begins at RVA 0x2058
        // Code size 23 (0x17)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Runtime]System.Attribute::.ctor()
        IL_0006: ldarg.0
        IL_0007: ldc.i4.1
        IL_0008: newarr [System.Runtime]System.Byte
        IL_000d: dup
        IL_000e: ldc.i4.0
        IL_000f: ldarg.1
        IL_0010: stelem.i1
        IL_0011: stfld uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
        IL_0016: ret
    } // end of method NullableAttribute::.ctor

    .method public hidebysig specialname rtspecialname 
        instance void .ctor (
            uint8[] ''
        ) cil managed 
    {
        // Method begins at RVA 0x2070
        // Code size 14 (0xe)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Runtime]System.Attribute::.ctor()
        IL_0006: ldarg.0
        IL_0007: ldarg.1
        IL_0008: stfld uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
        IL_000d: ret
    } // end of method NullableAttribute::.ctor

} // end of class System.Runtime.CompilerServices.NullableAttribute

.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
    extends [System.Runtime]System.Attribute
{
    .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void [System.Runtime]System.AttributeUsageAttribute::.ctor(valuetype [System.Runtime]System.AttributeTargets) = (
        01 00 4c 14 00 00 02 00 54 02 0d 41 6c 6c 6f 77
        4d 75 6c 74 69 70 6c 65 00 54 02 09 49 6e 68 65
        72 69 74 65 64 00
    )
    // Fields
    .field public initonly uint8 Flag

    // Methods
    .method public hidebysig specialname rtspecialname 
        instance void .ctor (
            uint8 ''
        ) cil managed 
    {
        // Method begins at RVA 0x207f
        // Code size 14 (0xe)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Runtime]System.Attribute::.ctor()
        IL_0006: ldarg.0
        IL_0007: ldarg.1
        IL_0008: stfld uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
        IL_000d: ret
    } // end of method NullableContextAttribute::.ctor

} // end of class System.Runtime.CompilerServices.NullableContextAttribute

.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.RefSafetyRulesAttribute
    extends [System.Runtime]System.Attribute
{
    .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void [System.Runtime]System.AttributeUsageAttribute::.ctor(valuetype [System.Runtime]System.AttributeTargets) = (
        01 00 02 00 00 00 02 00 54 02 0d 41 6c 6c 6f 77
        4d 75 6c 74 69 70 6c 65 00 54 02 09 49 6e 68 65
        72 69 74 65 64 00
    )
    // Fields
    .field public initonly int32 Version

    // Methods
    .method public hidebysig specialname rtspecialname 
        instance void .ctor (
            int32 ''
        ) cil managed 
    {
        // Method begins at RVA 0x208e
        // Code size 14 (0xe)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Runtime]System.Attribute::.ctor()
        IL_0006: ldarg.0
        IL_0007: ldarg.1
        IL_0008: stfld int32 System.Runtime.CompilerServices.RefSafetyRulesAttribute::Version
        IL_000d: ret
    } // end of method RefSafetyRulesAttribute::.ctor

} // end of class System.Runtime.CompilerServices.RefSafetyRulesAttribute



// .NET 8
.assembly _
{
    .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = (
        01 00 08 00 00 00 00 00
    )
    .custom instance void [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = (
        01 00 01 00 54 02 16 57 72 61 70 4e 6f 6e 45 78
        63 65 70 74 69 6f 6e 54 68 72 6f 77 73 01
    )
    .custom instance void [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (
        01 00 02 00 00 00 00 00
    )
    .permissionset reqmin = (
        2e 01 80 8a 53 79 73 74 65 6d 2e 53 65 63 75 72
        69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e
        53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69
        6f 6e 41 74 74 72 69 62 75 74 65 2c 20 53 79 73
        74 65 6d 2e 52 75 6e 74 69 6d 65 2c 20 56 65 72
        73 69 6f 6e 3d 38 2e 30 2e 30 2e 30 2c 20 43 75
        6c 74 75 72 65 3d 6e 65 75 74 72 61 6c 2c 20 50
        75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e 3d 62 30
        33 66 35 66 37 66 31 31 64 35 30 61 33 61 15 01
        54 02 10 53 6b 69 70 56 65 72 69 66 69 63 61 74
        69 6f 6e 01
    )
    .hash algorithm 0x00008004 // SHA1
    .ver 0:0:0:0
}

.class private auto ansi '<Module>'
{
} // end of class <Module>

.class public auto ansi beforefieldinit IntToString
    extends [System.Runtime]System.Object
{
    .custom instance void [BenchmarkDotNet]BenchmarkDotNet.Attributes.HideColumnsAttribute::.ctor(string[]) = (
        01 00 04 00 00 00 05 45 72 72 6f 72 06 53 74 64
        44 65 76 06 4d 65 64 69 61 6e 07 52 61 74 69 6f
        53 44 00 00
    )
    .custom instance void [BenchmarkDotNet]BenchmarkDotNet.Attributes.MemoryDiagnoserAttribute::.ctor(bool) = (
        01 00 00 00 00
    )
    .custom instance void [BenchmarkDotNet]BenchmarkDotNet.Attributes.ConfigAttribute::.ctor(class [System.Runtime]System.Type) = (
        01 00 12 49 6e 74 54 6f 53 74 72 69 6e 67 2b 43
        6f 6e 66 69 67 00 00
    )
    // Nested Types
    .class nested private auto ansi beforefieldinit Config
        extends [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig
    {
        // Methods
        .method public hidebysig specialname rtspecialname 
            instance void .ctor () cil managed 
        {
            // Method begins at RVA 0x2064
            // Code size 111 (0x6f)
            .maxstack 6

            // sequence point: (line 32, col 9) to (line 32, col 24) in _
            IL_0000: ldarg.0
            IL_0001: call instance void [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig::.ctor()
            // sequence point: (line 34, col 13) to (line 34, col 95) in _
            IL_0006: ldarg.0
            IL_0007: ldc.i4.1
            IL_0008: newarr [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job
            IL_000d: dup
            IL_000e: ldc.i4.0
            IL_000f: ldsfld !0 class [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobMode`1<class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job>::Default
            IL_0014: ldstr ".NET 7"
            IL_0019: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::WithId(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job, string)
            IL_001e: ldsfld class [BenchmarkDotNet]BenchmarkDotNet.Environments.CoreRuntime [BenchmarkDotNet]BenchmarkDotNet.Environments.CoreRuntime::Core70
            IL_0023: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::WithRuntime(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job, class [BenchmarkDotNet]BenchmarkDotNet.Environments.Runtime)
            IL_0028: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::AsBaseline(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job)
            IL_002d: stelem.ref
            IL_002e: call instance class [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig::AddJob(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job[])
            IL_0033: pop
            // sequence point: (line 35, col 13) to (line 35, col 82) in _
            IL_0034: ldarg.0
            IL_0035: ldc.i4.1
            IL_0036: newarr [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job
            IL_003b: dup
            IL_003c: ldc.i4.0
            IL_003d: ldsfld !0 class [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobMode`1<class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job>::Default
            IL_0042: ldstr ".NET 8"
            IL_0047: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::WithId(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job, string)
            IL_004c: ldsfld class [BenchmarkDotNet]BenchmarkDotNet.Environments.CoreRuntime [BenchmarkDotNet]BenchmarkDotNet.Environments.CoreRuntime::Core80
            IL_0051: call class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job [BenchmarkDotNet]BenchmarkDotNet.Jobs.JobExtensions::WithRuntime(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job, class [BenchmarkDotNet]BenchmarkDotNet.Environments.Runtime)
            IL_0056: stelem.ref
            IL_0057: call instance class [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig::AddJob(class [BenchmarkDotNet]BenchmarkDotNet.Jobs.Job[])
            IL_005c: pop
            // sequence point: (line 37, col 13) to (line 38, col 76) in _
            IL_005d: ldarg.0
            IL_005e: ldsfld class [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle::Default
            IL_0063: ldc.i4.1
            IL_0064: callvirt instance class [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle::WithRatioStyle(valuetype [BenchmarkDotNet]BenchmarkDotNet.Columns.RatioStyle)
            IL_0069: call instance void [BenchmarkDotNet]BenchmarkDotNet.Configs.ManualConfig::set_SummaryStyle(class [BenchmarkDotNet]BenchmarkDotNet.Reports.SummaryStyle)
            // sequence point: (line 39, col 9) to (line 39, col 10) in _
            IL_006e: ret
        } // end of method Config::.ctor

    } // end of class Config


    // Methods
    .method public hidebysig 
        instance string Int32ToString (
            int32 i
        ) cil managed 
    {
        .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
            01 00 01 00 00
        )
        .custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.BenchmarkAttribute::.ctor(int32, string) = (
            01 00 18 00 00 00 01 5f 00 00
        )
        .custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.ArgumentsAttribute::.ctor(object[]) = (
            01 00 01 00 00 00 08 0c 00 00 00 00 00
        )
        .custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.ArgumentsAttribute::.ctor(object[]) = (
            01 00 01 00 00 00 08 7b 00 00 00 00 00
        )
        .custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.ArgumentsAttribute::.ctor(object[]) = (
            01 00 01 00 00 00 08 d2 02 96 49 00 00
        )
        // Method begins at RVA 0x2050
        // Code size 8 (0x8)
        .maxstack 8

        // sequence point: (line 28, col 43) to (line 28, col 55) in _
        IL_0000: ldarga.s i
        IL_0002: call instance string [System.Runtime]System.Int32::ToString()
        IL_0007: ret
    } // end of method IntToString::Int32ToString

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x2059
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Runtime]System.Object::.ctor()
        IL_0006: ret
    } // end of method IntToString::.ctor

} // end of class IntToString

// .NET 7 (X64)
; Core CLR 7.0.1624.6629 on x64

IntToString..ctor()
    L0000: ret

IntToString.Int32ToString(Int32)
    L0000: sub rsp, 0x28
    L0004: mov ecx, edx
    L0006: call qword ptr [0x7ffa2c087300]
    L000c: nop
    L000d: add rsp, 0x28
    L0011: ret

IntToString+Config..ctor()
    L0000: push rdi
    L0001: push rsi
    L0002: push rbp
    L0003: push rbx
    L0004: sub rsp, 0x28
    L0008: mov rsi, rcx
    L000b: mov rcx, rsi
    L000e: call qword ptr [0x7ffa31c4f6a8]
    L0014: mov rcx, 0x7ffa321c2b18
    L001e: mov edx, 1
    L0023: call 0x00007ffa8ba5edc0
    L0028: mov rdi, rax
    L002b: mov rcx, 0x7ffa31c7b280
    L0035: xor edx, edx
    L0037: call 0x00007ffa8ba24d50
    L003c: mov rcx, 0x1c55ec6f418
    L0046: mov rbx, [rcx]
    L0049: mov rcx, 0x7ffa321c2848
    L0053: call 0x00007ffa8ba5ec40
    L0058: mov rbp, rax
    L005b: mov rdx, 0x1c55ec90398
    L0065: mov rdx, [rdx]
    L0068: mov rcx, rbp
    L006b: call qword ptr [0x7ffa321a38d0]
    L0071: mov rcx, rbp
    L0074: mov rdx, rbx
    L0077: call qword ptr [0x7ffa321a3228]
    L007d: mov r8, rax
    L0080: mov rdx, rbx
    L0083: mov rcx, rbp
    L0086: call qword ptr [0x7ffa321a3420]
    L008c: test rax, rax
    L008f: je short L00a4
    L0091: mov rcx, 0x7ffa321c2848
    L009b: cmp [rax], rcx
    L009e: jne L01e3
    L00a4: mov rcx, 0x7ffa31c7b280
    L00ae: mov edx, 0x1a8
    L00b3: call 0x00007ffa8ba5ee10
    L00b8: mov rdx, 0x1c55ec6da20
    L00c2: mov rdx, [rdx]
    L00c5: mov rcx, rbp
    L00c8: call qword ptr [0x7ffa321a5090]
    L00ce: mov rcx, rax
    L00d1: call qword ptr [0x7ffa321a55b8]
    L00d7: lea rcx, [rdi+0x10]
    L00db: mov rdx, rax
    L00de: call 0x00007ffa8ba5e4b0
    L00e3: mov rcx, rsi
    L00e6: mov rdx, rdi
    L00e9: call qword ptr [0x7ffa31c4f4e0]
    L00ef: mov rcx, 0x7ffa321c2b18
    L00f9: mov edx, 1
    L00fe: call 0x00007ffa8ba5edc0
    L0103: mov rdi, rax
    L0106: mov rcx, 0x1c55ec6f418
    L0110: mov rbx, [rcx]
    L0113: mov rcx, 0x7ffa321c2848
    L011d: call 0x00007ffa8ba5ec40
    L0122: mov rbp, rax
    L0125: mov rdx, 0x1c55ec903a0
    L012f: mov rdx, [rdx]
    L0132: mov rcx, rbp
    L0135: call qword ptr [0x7ffa321a38d0]
    L013b: mov rcx, rbp
    L013e: mov rdx, rbx
    L0141: call qword ptr [0x7ffa321a3228]
    L0147: mov r8, rax
    L014a: mov rdx, rbx
    L014d: mov rcx, rbp
    L0150: call qword ptr [0x7ffa321a3420]
    L0156: test rax, rax
    L0159: je short L016e
    L015b: mov rcx, 0x7ffa321c2848
    L0165: cmp [rax], rcx
    L0168: jne L01ed
    L016e: mov rdx, 0x1c55ec6da28
    L0178: mov rdx, [rdx]
    L017b: mov rcx, rbp
    L017e: call qword ptr [0x7ffa321a5090]
    L0184: lea rcx, [rdi+0x10]
    L0188: mov rdx, rax
    L018b: call 0x00007ffa8ba5e4b0
    L0190: mov rcx, rsi
    L0193: mov rdx, rdi
    L0196: call qword ptr [0x7ffa31c4f4e0]
    L019c: mov rcx, 0x7ffa31c7b280
    L01a6: mov edx, 0xf7
    L01ab: call 0x00007ffa8ba5ee10
    L01b0: mov rcx, 0x1c55ec6d4e8
    L01ba: mov rcx, [rcx]
    L01bd: mov edx, 1
    L01c2: cmp [rcx], ecx
    L01c4: call qword ptr [0x7ffa321a5a08]
    L01ca: lea rcx, [rsi+0x88]
    L01d1: mov rdx, rax
    L01d4: call 0x00007ffa8ba5e4b0
    L01d9: nop
    L01da: add rsp, 0x28
    L01de: pop rbx
    L01df: pop rbp
    L01e0: pop rsi
    L01e1: pop rdi
    L01e2: ret
    L01e3: mov rdx, rax
    L01e6: call qword ptr [0x7ffa2bf5b8b8]
    L01ec: int3
    L01ed: mov rdx, rax
    L01f0: call qword ptr [0x7ffa2bf5b8b8]
    L01f6: int3

Microsoft.CodeAnalysis.EmbeddedAttribute..ctor()
    L0000: ret

System.Runtime.CompilerServices.NullableAttribute..ctor(Byte)
    L0000: push rdi
    L0001: push rsi
    L0002: sub rsp, 0x28
    L0006: mov rsi, rcx
    L0009: mov edi, edx
    L000b: mov rcx, 0x7ffa2c078700
    L0015: mov edx, 1
    L001a: call 0x00007ffa8ba5ed60
    L001f: mov [rax+0x10], dil
    L0023: lea rcx, [rsi+8]
    L0027: mov rdx, rax
    L002a: call 0x00007ffa8ba5e4b0
    L002f: nop
    L0030: add rsp, 0x28
    L0034: pop rsi
    L0035: pop rdi
    L0036: ret

System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])
    L0000: lea rcx, [rcx+8]
    L0004: call 0x00007ffa8ba5e4b0
    L0009: nop
    L000a: ret

System.Runtime.CompilerServices.NullableContextAttribute..ctor(Byte)
    L0000: mov [rcx+8], dl
    L0003: ret

System.Runtime.CompilerServices.RefSafetyRulesAttribute..ctor(Int32)
    L0000: mov [rcx+8], edx
    L0003: ret
// .NET 8 (X64)
; Core CLR 8.0.123.58001 on x64

IntToString..ctor()
    L0000: ret

IntToString.Int32ToString(Int32)
    L0000: sub rsp, 0x28
    L0004: mov ecx, edx
    L0006: call qword ptr [0x7ffa8acc4300]
    L000c: nop
    L000d: add rsp, 0x28
    L0011: ret

IntToString+Config..ctor()
    L0000: push rdi
    L0001: push rsi
    L0002: push rbp
    L0003: push rbx
    L0004: sub rsp, 0x28
    L0008: mov rbx, rcx
    L000b: mov rcx, rbx
    L000e: call qword ptr [0x7ffa913c5938]
    L0014: mov rcx, 0x7ffa9151da18
    L001e: mov edx, 1
    L0023: call 0x00007ffaea73af90
    L0028: mov rsi, rax
    L002b: mov rcx, 0x7ffa913f6fa8
    L0035: xor edx, edx
    L0037: call 0x00007ffaea6ee880
    L003c: mov rcx, 0x1cfc9045910
    L0046: mov rdi, [rcx]
    L0049: mov rcx, 0x7ffa9151d770
    L0053: call 0x00007ffaea73ae10
    L0058: mov rbp, rax
    L005b: mov rdx, 0x1cfc90654c8
    L0065: mov rdx, [rdx]
    L0068: mov rcx, rbp
    L006b: call qword ptr [0x7ffa914fc810]
    L0071: mov rcx, rdi
    L0074: cmp [rcx], ecx
    L0076: call qword ptr [0x7ffa914fc150]
    L007c: mov r8, rax
    L007f: mov rcx, rbp
    L0082: mov rdx, rdi
    L0085: call qword ptr [0x7ffa914fc360]
    L008b: test rax, rax
    L008e: je short L00a3
    L0090: mov rcx, 0x7ffa9151d770
    L009a: cmp [rax], rcx
    L009d: jne L01cf
    L00a3: test byte ptr [0x7ffa913f717b], 1
    L00aa: je L01d9
    L00b0: mov rdx, 0x1cfc9043f28
    L00ba: mov rdx, [rdx]
    L00bd: mov rcx, rbp
    L00c0: call qword ptr [0x7ffa914fc9f0]
    L00c6: mov rcx, rax
    L00c9: call qword ptr [0x7ffa914fcf18]
    L00cf: lea rcx, [rsi+0x10]
    L00d3: mov rdx, rax
    L00d6: call 0x00007ffaea73a680
    L00db: mov rcx, rbx
    L00de: mov rdx, rsi
    L00e1: call qword ptr [0x7ffa913c5770]
    L00e7: mov rcx, 0x7ffa9151da18
    L00f1: mov edx, 1
    L00f6: call 0x00007ffaea73af90
    L00fb: mov rsi, rax
    L00fe: mov rcx, 0x1cfc9045910
    L0108: mov rbp, [rcx]
    L010b: mov rcx, 0x7ffa9151d770
    L0115: call 0x00007ffaea73ae10
    L011a: mov rdi, rax
    L011d: mov rdx, 0x1cfc90654d0
    L0127: mov rdx, [rdx]
    L012a: mov rcx, rdi
    L012d: call qword ptr [0x7ffa914fc810]
    L0133: mov rcx, rbp
    L0136: cmp [rcx], ecx
    L0138: call qword ptr [0x7ffa914fc150]
    L013e: mov r8, rax
    L0141: mov rcx, rdi
    L0144: mov rdx, rbp
    L0147: call qword ptr [0x7ffa914fc360]
    L014d: test rax, rax
    L0150: je short L0165
    L0152: mov rcx, 0x7ffa9151d770
    L015c: cmp [rax], rcx
    L015f: jne L01f2
    L0165: mov rdx, 0x1cfc9043f30
    L016f: mov rdx, [rdx]
    L0172: mov rcx, rdi
    L0175: call qword ptr [0x7ffa914fc9f0]
    L017b: lea rcx, [rsi+0x10]
    L017f: mov rdx, rax
    L0182: call 0x00007ffaea73a680
    L0187: mov rcx, rbx
    L018a: mov rdx, rsi
    L018d: call qword ptr [0x7ffa913c5770]
    L0193: test byte ptr [0x7ffa913f70ca], 1
    L019a: je short L01fc
    L019c: mov rcx, 0x1cfc90439f0
    L01a6: mov rcx, [rcx]
    L01a9: mov edx, 1
    L01ae: cmp [rcx], ecx
    L01b0: call qword ptr [0x7ffa914fd368]
    L01b6: lea rcx, [rbx+0x88]
    L01bd: mov rdx, rax
    L01c0: call 0x00007ffaea73a680
    L01c5: nop
    L01c6: add rsp, 0x28
    L01ca: pop rbx
    L01cb: pop rbp
    L01cc: pop rsi
    L01cd: pop rdi
    L01ce: ret
    L01cf: mov rdx, rax
    L01d2: call qword ptr [0x7ffa8aba43f0]
    L01d8: int3
    L01d9: mov rcx, 0x7ffa913f6fa8
    L01e3: mov edx, 0x1a3
    L01e8: call 0x00007ffaea73afe0
    L01ed: jmp L00b0
    L01f2: mov rdx, rax
    L01f5: call qword ptr [0x7ffa8aba43f0]
    L01fb: int3
    L01fc: mov rcx, 0x7ffa913f6fa8
    L0206: mov edx, 0xf2
    L020b: call 0x00007ffaea73afe0
    L0210: jmp short L019c


Benchmark Description:


I believe this is the primary [PR](https://github.com/dotnet/runtime/pull/79061) ***Looks like more numbers are cached, now up to 299.*** From Stephen Toub 'Performance Improvements in .NET 8' _the formatting code contained a table of precomputed strings for single digit numbers, so if you asked for the equivalent of 0.ToString(), the implementation wouldn’t need to allocate a new string, it would just fetch "0" from the table and return it. This PR expands that cache from single digit numbers to being all numbers 0 through 299 (it also makes the cache lazy, such that we don’t need to pay for the strings for values that are never used). The choice of 299 is somewhat arbitrary and could be raised in the future if the need presents itself, but in examining data from various services, this addresses a significant chunk of the allocations that come from number formatting. Coincidentally or not, it also includes all success status codes from the HTTP protocol._

The provided benchmark code is designed to measure the performance of converting integers to strings in .NET, specifically comparing the performance across different .NET versions. Below is an overview of the general setup and the specific rationale behind each benchmark method. ### General Setup - **.NET Versions:** The benchmark is configured to compare .NET 7 and .NET 8, indicating it's targeting future versions of .NET, assuming the knowledge cutoff date. This comparison aims to identify performance improvements or regressions between these versions. - **BenchmarkDotNet:** It uses BenchmarkDotNet, a powerful .NET library for benchmarking, providing detailed and accurate performance measurements. - **Configuration:** - **HideColumns:** It hides specific columns like Error, StdDev (Standard Deviation), Median, and RatioSD (Standard Deviation of the ratio) in the output results to focus on the most relevant data. - **MemoryDiagnoser:** Enabled with `displayGenColumns: false` to report memory allocation without showing garbage collection generation columns. This helps in understanding the memory footprint of the operation without cluttering the report with GC details. - **Jobs:** Two jobs are defined to test against .NET 7 (as the baseline) and .NET 8, allowing for a direct performance comparison between these two versions. - **SummaryStyle:** Configured to display ratio differences in percentage, making it easier to understand the performance differences. ### Benchmark Method: `Int32ToString` - **Purpose:** This method benchmarks the performance of converting an integer (`int`) to a string using the `ToString` method. - **Arguments:** It tests three different integer values (`12`, `123`, and `1_234_567_890`) to cover a range of scenarios: - A small integer (`12`): Tests the conversion efficiency for common, small numbers. - A medium integer (`123`): Slightly more complex than the small integer, testing the conversion efficiency for moderately sized numbers. - A large integer (`1_234_567_890`): Tests the conversion efficiency for large numbers, which might be more computationally intensive to convert due to their size. - **Performance Aspect:** This benchmark is designed to measure: - **Execution Time:** How quickly the .NET runtime can convert integers of various sizes to strings. - **Memory Allocation:** The amount of memory allocated during the conversion process. This is crucial for understanding the impact of this operation in memory-sensitive applications. - **Importance:** Converting integers to strings is a common operation in many applications, including formatting, logging, and data processing. Understanding the performance characteristics of this operation can help developers make informed decisions to optimize their applications. - **Expected Results/Insights:** - **Performance Improvement or Regression:** By comparing .NET 7 and .NET 8, developers can identify if there have been optimizations or degradations in performance for this operation. - **Impact of Integer Size:** The benchmark may reveal how the size of the integer affects the performance of its conversion to a string, providing insights into how different scenarios might behave in production environments. - **Memory Allocation Insights:** Understanding the memory footprint of this operation can help in optimizing applications, especially those running in environments where memory is a constraint. Running these benchmarks provides valuable insights into the performance characteristics of integer-to-string conversions across different .NET versions, helping developers optimize their code for better performance and efficiency.


Benchmark Comments: