静态属性/函数的性能

本文关键字:性能 函数 属性 静态 | 更新日期: 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检查。

但是,除非调用位于热点(经常调用),否则这种差异可以忽略不计。