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): Tag(s):
Added By:
.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);
}
}
}
Powered by SharpLab
// .NET 7, .NET 8
public string Int32ToString(int i)
{
return i.ToString();
}
Powered by SharpLab
// .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
Powered by SharpLab
|
|
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.