静态属性/函数的性能
本文关键字:性能 函数 属性 静态 | 更新日期: 2023-09-27 17:48:56
将属性设置为静态/共享时,性能是否与以前的实例属性有差异,可能有任何锁定机制?
在httpache中有一个被大量使用的对象,它可以通过页面实例(Service.aspx)中的属性来访问。现在我想知道如果它是静态的会更好,因为HttpCache是在整个应用程序中共享的。
我决定把它变成静态的主要原因是它更容易被引用(Service.dsRMA
vs. ((Service)Page).dsRMA
)。
我知道在静态函数和线程安全方面可能发生的问题。
感谢您的宝贵时间。
前:
c#public ERPModel.dsRMA dsRMA {
get {
if (Cache("DS_RMA") == null) {
Cache("DS_RMA") = new ERPModel.dsRMA();
}
return (ERPModel.dsRMA)Cache("DS_RMA");
}
}
VB
Public ReadOnly Property dsRMA() As ERPModel.dsRMA
Get
If Cache("DS_RMA") Is Nothing Then
Cache("DS_RMA") = New ERPModel.dsRMA
End If
Return DirectCast(Cache("DS_RMA"), ERPModel.dsRMA)
End Get
End Property
后:
c#public static ERPModel.dsRMA dsRMA {
get {
if (HttpContext.Current.Cache("DS_RMA") == null) {
HttpContext.Current.Cache("DS_RMA") = new ERPModel.dsRMA();
}
return (ERPModel.dsRMA)HttpContext.Current.Cache("DS_RMA");
}
}
VB
Public Shared ReadOnly Property dsRMA() As ERPModel.dsRMA
Get
If HttpContext.Current.Cache("DS_RMA") Is Nothing Then
HttpContext.Current.Cache("DS_RMA") = New ERPModel.dsRMA
End If
Return DirectCast(HttpContext.Current.Cache("DS_RMA"), ERPModel.dsRMA)
End Get
End Property
您不太可能注意到任何显著的性能差异。(如果有的话,我希望静态版本具有轻微的性能优势。如果微优化真的很重要,测试基准,看看在你的特定情况下会发生什么。
我建议在你的应用程序领域的上下文中做任何最有语义意义的事情:如果对象在逻辑上属于一个特定的实例,那么使用实例属性;如果对象在所有实例之间共享,则使用静态属性
如果没有任何线程或管理问题,静态方法更快(不是非常快),实际上实例方法是带有隐式this
参数的静态方法。
编辑:我说静态方法和实例方法不同是这样的,我并不是指调用的方式,第一个是在堆中管理的,第二个是在堆栈中管理的。
我在这里有一篇文章概述了各种锁定方法。这最初是为BizTalk编写的,但适用于通用的。net。
我已经解释了双if
夹夹lock
语句阻止race conditions
。这就是文章中的TopCache
。请阅读文章的最后三分之一。
更新关于静态方法性能的一句话。静态方法由CLR
call
调用,而实例方法通常由callvirt
调用。callvirt
是一个虚调用,必须在继承层次结构中查找要调用的方法。这将造成一些开销,但几乎可以忽略不计。异常(例如显式接口实现)不在这个问题的范围内。
从CLR到c#:
callvirt IL指令可以是用于调用实例和虚拟方法,而不是静态方法。当Callvirt指令用于调用一个实例或虚方法必须指定一个引用的变量一个对象。当callvirt IL指令用于调用非虚拟实例方法,类型变量的值表示哪种类型定义CLR应该使用的方法呼叫当调用virt IL指令时用于调用虚拟实例方法,CLR发现实际的用于制作的对象的类型然后调用该方法以多态方式。为了确定类型,用于的变量Make call不能为空。在换句话说,当编译这个调用时,JIT编译器生成的代码验证变量的值为非空。如果为空,callvirt指令导致CLR抛出得到NullReferenceException。这附加检查意味着callvirt IL指令执行比通话稍微慢一点指令。注意这个空检查即使callvirt指令用于调用非虚拟实例方法。
静态方法比实例方法稍微快一些(参见这个问题)。实例方法在对目标对象调用方法之前有一个额外的null ref检查。
但是,除非调用位于热点(经常调用),否则这种差异可以忽略不计。