具有和不具有静态构造函数的静态类型性能

时间:2013-05-08 09:52:03

标签: c# .net

在他的article关于“性能与懒惰”段落中的单身人士中,Jon Skeet写了以下几行:

  

如果您的单例实例在相对较紧的范围内被引用   循环,这可以产生(相对)显着的性能差异。

据我了解,他的意思是两种情况之间的区别:有和没有静态构造函数。

但是,尽管有这些话,但这种差异的原因对我来说仍然含糊不清:

  

这可以提高性能,因为它允许JIT编译器创建   单一检查(例如在方法的开头)以确保   该类型已初始化,然后从此开始承担。

如果存在静态构造函数,那么JIT编译器会做什么?

3 个答案:

答案 0 :(得分:1)

两种方法都没有太大的性能差异。除非你在一个紧密的循环中调用它们。

单例和静态类之间的最大区别在于单例可以实现接口。你可以将单例类作为参数传递。

修改


  

除非你在紧密的循环中呼叫它们

单例实例变体较慢,因为您必须访问两个内存操作才能获得该值。

  1. 静态存储
  2. 和正常的内存存储

    但是对于正常的电话来说,差别可以忽略不计。当你在一个巨大的循环中调用它时,这种差异将会增加,而静态类在这种情况下会表现得更好。

答案 1 :(得分:0)

Jon Skeet实际上指的是在创建单例对象的实例时。如果你在静态构造函数中创建它,那么框架确保它只执行一次并且不需要取出锁。

但是,如果你在第一次访问时使用Lazy或使用一些自定义代码来生成实例,那么这可能会更慢。

他说如果你在循环中访问单例实例,那么静态构造函数会更快。

答案 2 :(得分:0)

我通过CA1810 rule explanation找到了关于效果的答案。

  

当一个类型声明一个显式静态构造函数时,即时   (JIT)编译器为每个静态方法和实例添加一个检查   类型的构造函数,以确保静态构造函数是   以前叫过。任何静态时都会触发静态初始化   访问成员或创建类型的实例时。   但是,如果声明a,则不会触发静态初始化   类型的变量但不使用它,如果是的话,这可能很重要   初始化改变全局状态。当所有静态数据都是   初始化内联并且未声明显式静态构造函数,   Microsoft中间语言(MSIL)编译器添加了   beforefieldinit标志和隐式静态构造函数,其中   将静态数据初始化为MSIL类型定义。当JIT   编译器遇到beforefieldinit标志,大部分时间都是   不添加静态构造函数检查。静态初始化是   保证在访问任何静态字段之前的某个时间发生   但不是在调用静态方法或实例构造函数之前。   请注意,静态初始化可以在变量之后的任何时间发生   声明了类型。