在使静态/共享属性成为之前的实例属性(可能是任何锁定机制)时,性能是否存在差异?
HttpCache中有一个使用频繁的对象,可以通过页面实例(Service.aspx)中的属性访问。现在我想知道将它设置为静态是否更好,因为无论如何HttpCache在应用程序中共享。
我决定将其设为静态的主要原因是因为它更容易引用(Service.dsRMA
与((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
答案 0 :(得分:6)
您不太可能注意到任何重大的性能差异。 (如果有的话,我希望静态版本具有轻微的性能优势。基准测试,看看如果微优化真的很重要,在您的特定情况下会发生什么。)
我建议在应用程序域的上下文中执行最多语义意义的事情:如果对象在逻辑上属于特定实例,则使用实例属性;如果对象在所有实例之间共享,则使用静态属性。
答案 1 :(得分:3)
如果没有任何线程或管理问题,静态方法会更快(不是非常快),实际上实例方法是带有隐式this
参数的静态方法。
编辑:通过说静态方法和实例方法不同,我不是指调用方式,第一个是在堆中管理,第二个是在堆栈中管理。
答案 2 :(得分:2)
我有一篇文章here,其中概述了各种锁定方法。这最初是为BizTalk编写的,但适用于一般的.NET。
我已经解释了加倍if
对lock
语句进行了修改,这会阻止race conditions
。这就是文章中的TopCache
。请阅读文章的后三分之一。
关于静态方法性能的一个词。静态方法由CLR call
调用,而实例方法通常由callvirt
调用。作为虚拟调用的callvirt
必须通过继承层次结构来找出要调用的方法。这会导致一些开销,但几乎可以忽略不计。有例外(例如显式接口实现),这超出了这个问题的范围。
从CLR到C#:
callvirt IL指令可以 用于调用实例和虚拟 方法,而不是静态方法。当。。。的时候 callvirt指令用于调用 你是一个实例或虚拟方法 必须指定引用的变量 一个东西。当callvirt IL 指令用于调用a 非虚拟实例方法,类型 变量表示哪种类型 定义了CLR应该采用的方法 呼叫。当callvirt IL指令 用于调用虚拟实例 方法,CLR发现实际 用于制作的对象的类型 调用然后调用方法 多态。它命令确定 类型,用于的变量 使调用不能为空。在 换句话说,在编译此调用时, JIT编译器生成代码 验证变量的值是否为 不是空的。如果它为null,则为callvirt 指令导致CLR抛出一个 NullReferenceException异常。这个 额外检查意味着 callvirt IL指令执行 比电话慢一点 指令。注意这个空检查 即使在callvirt中也会执行 指令用于调用a 非虚拟实例方法。
答案 3 :(得分:2)
静态方法比实例方法稍快(参见this question)。在对目标对象调用方法之前,实例方法有一个额外的空引用检查。
但是话说,除非呼叫处于热点(频繁呼叫),否则这种差异是可以忽略不计的。