Skip to content

Instantly share code, notes, and snippets.

@guitarrapc
Last active October 31, 2021 14:34
Show Gist options
  • Save guitarrapc/3611f37df9159c43795ade355c2db1e9 to your computer and use it in GitHub Desktop.
Save guitarrapc/3611f37df9159c43795ade355c2db1e9 to your computer and use it in GitHub Desktop.
Inline optimization and string Interpolation. https://twitter.com/badamczewski01/status/1453993632365699072?s=20
BenchmarkRunner.Run<BenchmarkInline>();
[BenchmarkDotNet.Attributes.MemoryDiagnoser]
public class BenchmarkInline
{
[Benchmark]
public void StringInterpolationInline() => PrintAInline(0);
[Benchmark]
public void StringInterpolationNoInline() => PrintANoInline(0);
[Benchmark]
public void ToStringInline() => PrintBInline(0);
[Benchmark]
public void ToStringNoInline() => PrintBNoInline(0);
// default no-inlining (!?)
string PrintANoInline(int x) => $"{x}";
[MethodImpl(MethodImplOptions.AggressiveInlining)]
string PrintAInline(int x) => $"{x}";
// default inlining
string PrintBInline(int x) => x.ToString();
[MethodImpl(MethodImplOptions.NoInlining)]
string PrintBNoInline(int x) => x.ToString();
}
// Validating benchmarks:
Assembly LINQPadQuery, Version=1.0.0.421, Culture=neutral, PublicKeyToken=null is located in temp. If you are running benchmarks from xUnit you need to disable shadow copy. It's not supported by design.
// ***** BenchmarkRunner: Start *****
// * Summary *
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000
AMD Ryzen 9 5900X, 1 CPU, 24 logical and 12 physical cores
.NET SDK=6.0.100-rc.2.21505.57
[Host] : .NET 5.0.11 (5.0.1121.47308), X64 RyuJIT
| Method | Mean | Error | StdDev | Gen 0 | Allocated |
|---------------------------- |----------:|----------:|----------:|-------:|----------:|
| StringInterpolationInline | 30.626 ns | 0.1695 ns | 0.1585 ns | 0.0029 | 48 B |
| StringInterpolationNoInline | 31.610 ns | 0.2515 ns | 0.2353 ns | 0.0029 | 48 B |
| ToStringInline | 2.353 ns | 0.0046 ns | 0.0040 ns | - | - |
| ToStringNoInline | 3.205 ns | 0.0072 ns | 0.0067 ns | - | - |
// * Legends *
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Gen 0 : GC Generation 0 collects per 1000 operations
Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
1 ns : 1 Nanosecond (0.000000001 sec)
// * Diagnostic Output - MemoryDiagnoser *
// ***** BenchmarkRunner: End *****
// ** Remained 0 benchmark(s) to run **
Run time: 00:01:17 (77.95 sec), executed benchmarks: 4
Global total time: 00:01:17 (77.95 sec), executed benchmarks: 4
// * Artifacts cleanup *
void A(int a) => PrintAInline(a);
void B(int a) => PrintANoInline(a);
void C(int a) => PrintBInline(a);
void D(int a) => PrintBNoInline(a);
// default no-inlining (!?)
void PrintANoInline(int x) => Console.WriteLine($"{x}");
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void PrintAInline(int x) => Console.WriteLine($"{x}");
// default inlining
void PrintBInline(int x) => Console.WriteLine(x.ToString());
[MethodImpl(MethodImplOptions.NoInlining)]
void PrintBNoInline(int x) => Console.WriteLine(x.ToString());
<Main>g__A|4_0 (Int32)
IL_0000 ldarg.0
IL_0001 call UserQuery.<Main>g__PrintAInline|4_5 (Int32)
IL_0006 ret
<Main>g__B|4_1 (Int32)
IL_0000 ldarg.0
IL_0001 call UserQuery.<Main>g__PrintANoInline|4_4 (Int32)
IL_0006 ret
<Main>g__C|4_2 (Int32)
IL_0000 ldarg.0
IL_0001 call UserQuery.<Main>g__PrintBInline|4_6 (Int32)
IL_0006 ret
<Main>g__D|4_3 (Int32)
IL_0000 ldarg.0
IL_0001 call UserQuery.<Main>g__PrintBNoInline|4_7 (Int32)
IL_0006 ret
<Main>g__PrintANoInline|4_4 (Int32)
IL_0000 ldloca.s 00
IL_0002 ldc.i4.0
IL_0003 ldc.i4.1
IL_0004 call DefaultInterpolatedStringHandler..ctor
IL_0009 ldloca.s 00
IL_000B ldarg.0
IL_000C call DefaultInterpolatedStringHandler.AppendFormatted<Int32> (Int32)
IL_0011 ldloca.s 00
IL_0013 call DefaultInterpolatedStringHandler.ToStringAndClear ()
IL_0018 call Console.WriteLine (String)
IL_001D ret
<Main>g__PrintAInline|4_5 (Int32)
IL_0000 ldloca.s 00
IL_0002 ldc.i4.0
IL_0003 ldc.i4.1
IL_0004 call DefaultInterpolatedStringHandler..ctor
IL_0009 ldloca.s 00
IL_000B ldarg.0
IL_000C call DefaultInterpolatedStringHandler.AppendFormatted<Int32> (Int32)
IL_0011 ldloca.s 00
IL_0013 call DefaultInterpolatedStringHandler.ToStringAndClear ()
IL_0018 call Console.WriteLine (String)
IL_001D ret
<Main>g__PrintBInline|4_6 (Int32)
IL_0000 ldarga.s 00
IL_0002 call Int32.ToString ()
IL_0007 call Console.WriteLine (String)
IL_000C ret
<Main>g__PrintBNoInline|4_7 (Int32)
IL_0000 ldarga.s 00
IL_0002 call Int32.ToString ()
IL_0007 call Console.WriteLine (String)
IL_000C ret
<Main>g__A|4_0 (Int32)
L0000 push rdi
L0001 push rsi
L0002 push rbx
L0003 sub rsp, 0x50
L0007 xor eax, eax
L0009 mov [rsp+0x28], rax
L000e vxorps xmm4, xmm4, xmm4
L0012 vmovdqa [rsp+0x30], xmm4
L0018 vmovdqa [rsp+0x40], xmm4
L001e mov esi, ecx
L0020 mov rcx, 0x18bd7742f68
L002a mov rcx, [rcx]
L002d mov edx, 0x100
L0032 call qword ptr [0x7ff98d0f0998]
L0038 lea rdi, [rsp+0x28]
L003d mov [rsp+0x30], rax
L0042 test rax, rax
L0045 je short L008a
L0047 lea r8, [rax+0x10]
L004b mov ebx, [rax+8]
L004e add rdi, 0x18
L0052 mov [rdi], r8
L0055 mov [rdi+8], ebx
L0058 xor ecx, ecx
L005a mov [rsp+0x38], ecx
L005e mov byte ptr [rsp+0x3c], 0
L0063 lea rcx, [rsp+0x28]
L0068 mov edx, esi
L006a call System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted[[System.Int32, System.Private.CoreLib]](Int32)
L006f lea rcx, [rsp+0x28]
L0074 call System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()
L0079 mov rcx, rax
L007c call System.Console.WriteLine(System.String)
L0081 nop
L0082 add rsp, 0x50
L0086 pop rbx
L0087 pop rsi
L0088 pop rdi
L0089 ret
L008a xor r8d, r8d
L008d xor ebx, ebx
L008f jmp short L004e
<Main>g__B|4_1 (Int32)
L0000 jmp UserQuery.<Main>g__PrintANoInline|4_4(Int32)
<Main>g__C|4_2 (Int32)
L0000 sub rsp, 0x28
L0004 call System.Number.Int32ToDecStr(Int32)
L0009 mov rcx, rax
L000c call System.Console.WriteLine(System.String)
L0011 nop
L0012 add rsp, 0x28
L0016 ret
<Main>g__D|4_3 (Int32)
L0000 jmp UserQuery.<Main>g__PrintBNoInline|4_7(Int32)
<Main>g__PrintANoInline|4_4 (Int32)
L0000 push rdi
L0001 push rsi
L0002 push rbx
L0003 sub rsp, 0x50
L0007 xor eax, eax
L0009 mov [rsp+0x28], rax
L000e vxorps xmm4, xmm4, xmm4
L0012 vmovdqa [rsp+0x30], xmm4
L0018 vmovdqa [rsp+0x40], xmm4
L001e mov esi, ecx
L0020 mov rcx, 0x18bd7742f68
L002a mov rcx, [rcx]
L002d mov edx, 0x100
L0032 call qword ptr [0x7ff98d0f0998]
L0038 lea rdi, [rsp+0x28]
L003d mov [rsp+0x30], rax
L0042 test rax, rax
L0045 je short L008a
L0047 lea r8, [rax+0x10]
L004b mov ebx, [rax+8]
L004e add rdi, 0x18
L0052 mov [rdi], r8
L0055 mov [rdi+8], ebx
L0058 xor ecx, ecx
L005a mov [rsp+0x38], ecx
L005e mov byte ptr [rsp+0x3c], 0
L0063 lea rcx, [rsp+0x28]
L0068 mov edx, esi
L006a call System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted[[System.Int32, System.Private.CoreLib]](Int32)
L006f lea rcx, [rsp+0x28]
L0074 call System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()
L0079 mov rcx, rax
L007c call System.Console.WriteLine(System.String)
L0081 nop
L0082 add rsp, 0x50
L0086 pop rbx
L0087 pop rsi
L0088 pop rdi
L0089 ret
L008a xor r8d, r8d
L008d xor ebx, ebx
L008f jmp short L004e
<Main>g__PrintAInline|4_5 (Int32)
L0000 push rdi
L0001 push rsi
L0002 push rbx
L0003 sub rsp, 0x50
L0007 xor eax, eax
L0009 mov [rsp+0x28], rax
L000e vxorps xmm4, xmm4, xmm4
L0012 vmovdqa [rsp+0x30], xmm4
L0018 vmovdqa [rsp+0x40], xmm4
L001e mov esi, ecx
L0020 mov rcx, 0x18bd7742f68
L002a mov rcx, [rcx]
L002d mov edx, 0x100
L0032 call qword ptr [0x7ff98d0f0998]
L0038 lea rdi, [rsp+0x28]
L003d mov [rsp+0x30], rax
L0042 test rax, rax
L0045 je short L008a
L0047 lea r8, [rax+0x10]
L004b mov ebx, [rax+8]
L004e add rdi, 0x18
L0052 mov [rdi], r8
L0055 mov [rdi+8], ebx
L0058 xor ecx, ecx
L005a mov [rsp+0x38], ecx
L005e mov byte ptr [rsp+0x3c], 0
L0063 lea rcx, [rsp+0x28]
L0068 mov edx, esi
L006a call System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted[[System.Int32, System.Private.CoreLib]](Int32)
L006f lea rcx, [rsp+0x28]
L0074 call System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()
L0079 mov rcx, rax
L007c call System.Console.WriteLine(System.String)
L0081 nop
L0082 add rsp, 0x50
L0086 pop rbx
L0087 pop rsi
L0088 pop rdi
L0089 ret
L008a xor r8d, r8d
L008d xor ebx, ebx
L008f jmp short L004e
<Main>g__PrintBInline|4_6 (Int32)
L0000 sub rsp, 0x28
L0004 call System.Number.Int32ToDecStr(Int32)
L0009 mov rcx, rax
L000c call System.Console.WriteLine(System.String)
L0011 nop
L0012 add rsp, 0x28
L0016 ret
<Main>g__PrintBNoInline|4_7 (Int32)
L0000 sub rsp, 0x28
L0004 call System.Number.Int32ToDecStr(Int32)
L0009 mov rcx, rax
L000c call System.Console.WriteLine(System.String)
L0011 nop
L0012 add rsp, 0x28
L0016 ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment