【发布时间】:2022-01-22 13:12:53
【问题描述】:
我了解当一个类型声明一个显式静态构造函数时,即时 (JIT) 编译器会对该类型的每个静态方法和实例构造函数添加检查,以确保之前调用了静态构造函数。
这种行为我可以想象成如下代码(如果我对这个结论有误,请纠正我):
class ExplicitConstructor
{
private static string myVar;
// Force “precise” initialization
static ExplicitConstructor() { myVar = "hello, world";}
/* CLR: if the type constructor didn't invoked
then add a call to the type constructor */
public static string MyProperty
{
get { return myVar; }
}
/* CLR: if the type constructor didn't invoked
then add a call to the type constructor */
public ExplicitConstructor()
{
Console.WriteLine("In instance ctor");
}
}
class ImplicitConstructor
{
private static string myVar = "hello, world";
public static string MyProperty
{
/* CLR: Invoke the type constructor only here */
get { return myVar; }
}
public ImplicitConstructor()
{
Console.WriteLine("In instance ctor");
}
}
根据performance rules,这种行为会对性能产生影响,因为运行时会执行检查以在精确的时间运行类型初始化程序。
[MemoryDiagnoser]
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
[RankColumn]
public class BenchmarkExample
{
public const int iteration = Int32.MaxValue - 1;
[Benchmark]
public void BenchExplicitConstructor()
{
for (int i = 0; i < iteration; i++)
{
var temp = ExplicitConstructor.MyProperty;
}
}
[Benchmark]
public void BenchImplicitConstructor()
{
for (int i = 0; i < iteration; i++)
{
var temp = ImplicitConstructor.MyProperty;
}
}
}
| Method | Mean | Error | StdDev | Rank | Allocated |
|---|---|---|---|---|---|
| BenchImplicitConstructor | 982.6 ms | 56.64 ms | 163.4 ms | 1 | - |
| BenchExplicitConstructor | 7,361.4 ms | 318.19 ms | 933.2 ms | 2 | - |
为什么 CLR 不检查该类型的每个静态方法/实例构造函数以确保先前调用了该类型构造函数,而是检查该类型构造函数是否已被调用(仅一次)?
【问题讨论】:
-
Stopwatch和DateTime不是合适的基准测试工具......永远。首先考虑使用 BenchmarkDotNet 解决所有基准问题 -
@TheGeneral - 谢谢。我已经编辑了问题。
-
能否请您发布您的基准测试结果?
-
@Clemens - 是的,我会的。