首页 文章

静态方法与实例方法的性能

提问于
浏览
90

我的问题涉及静态方法与实例方法的性能特征及其可伸缩性 . 假设在这种情况下,所有类定义都在一个程序集中,并且需要多个离散指针类型 .

考虑:

public sealed class InstanceClass
{
      public int DoOperation1(string input)
      {
          // Some operation.
      }

      public int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more instance methods.
}

public static class StaticClass
{
      public static int DoOperation1(string input)
      {
          // Some operation.
      }

      public static int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more static methods.
}

上面的类表示辅助样式模式 .

在实例类中,解析实例方法需要花费一些时间来与StaticClass相反 .

我的问题是:

  • 当保持状态不是问题(不需要字段或属性)时,使用静态类总是更好吗?

  • 如果有相当多的静态类定义(例如100,每个都有许多静态方法),与相同数量的实例类定义相比,这会对执行性能或内存消耗产生负面影响吗?

  • 当调用同一实例类中的另一个方法时,实例解析是否仍然存在?例如,在同一实例的 DoOperation1 中使用[this]关键字,如 this.DoOperation2("abc") .

3 回答

  • 0

    理论上,静态方法应该比实例方法稍好一些,所有其他条件都相同,因为额外隐藏的 this 参数 .

    在实践中,这几乎没有什么区别,它将隐藏在各种编译器决策的噪声中 . (因此,两个人可能比另一个人有更好的结果) . 尤其是因为 this 通常在寄存器中传递,并且通常在该寄存器中开始 .

    最后一点意味着理论上,我们应该期望一个静态方法,它将一个对象作为一个参数,并用它做一些事情,比同一个对象上的一个实例稍微好一些 . 尽管如此,差异是如此之小,如果你试图测量它,你可能最终会测量其他一些编译器的决定 . (特别是因为该参考在整个时间内在寄存器中的可能性也非常高) .

    真正的性能差异将取决于你是否人为地将内存中的对象做成了一些自然应该是静态的东西,或者你是以复杂的方式纠缠于对象传递链以做自然应该实例化的事情 .

    因此对于数字1.当保持状态isn 't a concern, it' s总是更好的静态, because that's what static is for . 更有可能的是,有人去努力优化正常使用的案例,而不是那些出现奇怪用法的案例 .

    2号没有区别 . 每个成员都有一定数量的每类成本,它包括有多少元数据,实际DLL或EXE文件中有多少代码,以及有多少jitted代码 . 无论是实例还是静态,都是一样的 .

    对于第3项, thisthis 一样 . 但请注意:

    • this 参数在特定寄存器中传递 . 在同一个类中调用实例方法时,它可能已经存在于该寄存器中(除非它被存储并且由于某种原因使用了寄存器),因此不需要将 this 设置为需要设置的操作至 . 这在某种程度上适用于例如方法的前两个参数是它所做的调用的前两个参数 .

    • 由于很明显 this 不为空,因此在某些情况下可以使用它来优化调用 .

    • 由于很明显 this 不是null,这可能会使内联方法调用再次变得更有效,因为伪造方法调用所产生的代码可以省略它可能需要的一些空值检查 .

    • 那就是说,空检查很便宜!

    值得注意的是,在没有为给定类型调用给定静态的情况下,作用于对象而非实例方法的通用静态方法可以减少在http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-the-associated-overheads/讨论的一些成本 . 正如他所说的"As an aside, it turns out that extension methods are a great way to make generic abstractions more pay-for-play."

    但是,请注意,这仅涉及该方法使用的其他类型的实例化,否则不存在 . 因此,它确实不适用于很多情况(某些其他实例方法使用该类型,其他一些代码使用该类型) .

    摘要:

    • 大多数实例与静态的性能成本低于可忽略不计 .

    • 通常会出现滥用静态的成本,反之亦然 . 如果您没有在静态和实例之间做出决定,那么您更有可能获得正确的结果 .

    • 在极少数情况下,另一种类型的静态泛型方法导致创建的类型少于实例泛型方法,这些方法可以使 sometimes 具有很少的好处来转向很少使用(并且"rarely"指的是's used with in the lifetime of the application, not how often it'调用的类型) . 一旦你得到了什么,他就会发现它与大多数静态vs实例决策无关 . 编辑:它主要只有ngen的成本,而不是jitted代码 .

    编辑:关于公正的说明如何廉价的空检(我在上面声称) . .NET中的大多数空值检查都不起作用,如果发生访问异常,它将变为 NullReferenceException . 因此,大多数情况下,从概念上讲,C#代码涉及进行空检查,因为它正在访问实例成员,如果成功则成本实际为零 . 一个例外是一些内联调用,(因为他们希望表现得好像他们调用了一个实例成员)并且他们只是按一个字段来触发相同的行为,因此它们也非常便宜,但它们仍然经常被遗漏(例如,如果方法的第一步涉及访问字段) .

  • 6

    当保持状态不是问题(不需要字段或属性)时,使用静态类总是更好吗?

    我会说,是的 . 宣布一些事情 static 你声明了无状态执行的意图(这不是强制性的,而是一种人们期望的意图)

    如果有相当多的静态类(例如100个,每个都有许多静态方法),与相同数量的实例类相比,这会对执行性能或内存消耗产生负面影响吗?

    唐't think so, unless you'确保静态类真的无法进入,因为如果不是,它很容易搞乱内存分配并导致内存泄漏 .

    当[this]关键字用于调用同一实例类中的另一个方法时,实例解析是否仍然存在?

    不确定,关于这一点(这是CLR的纯粹实现细节),但是想一想 .

  • 124

    静态方法更快但是OOP更少,如果你将使用设计模式静态方法可能是坏代码,更好地编写业务逻辑而不需要静态,常见的函数如文件读取,WebRequest等更好地实现静态...你的问题没有普遍性回答

相关问题