Created
December 4, 2020 10:59
-
-
Save gfoidl/45d1f4b47fae81f49656d4c52a169ac9 to your computer and use it in GitHub Desktop.
Codegen for ModuleInitializer and static readonly fields
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.CompilerServices; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Running; | |
BenchmarkRunner.Run<Bench>(); | |
[ShortRunJob] | |
[DisassemblyDiagnoser] | |
public class Bench | |
{ | |
[Benchmark] | |
public double GetConstValue_DefaultConst() => DefaultConst.Sqrt2; | |
[Benchmark] | |
public double GetConstValue_CCtorConst() => CCtorConst.Sqrt2; | |
[Benchmark] | |
public double GetConstValue_ModuleInitializerConst() => ModuleInitializerConst.Sqrt2; | |
[Benchmark] | |
public double UseValueInLoop_DefaultConst() | |
{ | |
double s = 0; | |
for (int i = 0; i < 1_000; ++i) | |
{ | |
s += DefaultConst.Sqrt2; | |
} | |
return s; | |
} | |
[Benchmark] | |
public double UseValueInLoop_CCtorConst() | |
{ | |
double s = 0; | |
for (int i = 0; i < 1_000; ++i) | |
{ | |
s += CCtorConst.Sqrt2; | |
} | |
return s; | |
} | |
[Benchmark] | |
public double UseValueInLoop_ModuleInitializerConst() | |
{ | |
double s = 0; | |
for (int i = 0; i < 1_000; ++i) | |
{ | |
s += ModuleInitializerConst.Sqrt2; | |
} | |
return s; | |
} | |
} | |
public static class DefaultConst | |
{ | |
public static readonly double Sqrt2 = Math.Sqrt(2); | |
} | |
public static class CCtorConst | |
{ | |
public static readonly double Sqrt2; | |
static CCtorConst() => Sqrt2 = Math.Sqrt(2); | |
} | |
public static class ModuleInitializerConst | |
{ | |
public static readonly double Sqrt2 = Math.Sqrt(2); | |
[ModuleInitializer] | |
public static void DummyAccessToInit() | |
{ | |
_ = Sqrt2; | |
} | |
} |
(At least for .NET 6) a cctor and module initializer yield good code too.
public static class CCtorConst1
{
public static readonly double Sqrt2;
static CCtorConst1() => Sqrt2 = Math.Sqrt(2);
[ModuleInitializer]
internal static void Init()
{
_ = Sqrt2;
}
}
results in the same code as with ModuleInitializerConst
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Side note
Codegen for the loop can be improved by "breaking" the CSE in the JIT.
Tracking issue: dotnet/runtime#35257
C# code