【问题标题】:Do C# static functions perform better than nonstatic functions, beyond reduced memory usage?除了减少内存使用之外,C# 静态函数是否比非静态函数执行得更好?
【发布时间】:2011-01-17 12:14:55
【问题描述】:

我假设 publicprivate static 目标必须减少内存使用,因为内存中只有一个静态目标副本。

似乎是因为方法是静态的,这可能使该方法成为 CLR 编译器进一步优化的潜在点,超出了非静态函数的可能。不过这只是一个站不住脚的理论,所以我特地来问大家。

static publicprivate 方法除了减少内存使用量之外,还能提供任何更高的性能优势吗?

(注意:我对谈论过早优化问题的回复不感兴趣。当然,这是我每天都遵循的合理建议,但这并不意味着有时不需要优化。(双重否定!)。请允许我至少满足我的好奇心)

【问题讨论】:

  • 在 C# 中它们被称为方法而不是函数 :)

标签: c# performance optimization static keyword


【解决方案1】:

来自Static Classes and Static Class Members (C# Programming Guide)

对静态方法的调用会生成一个 微软的呼叫指令 中间语言(MSIL),而 对实例方法的调用会生成 一个 callvirt 指令,它也 检查空对象引用。 然而,大多数时候 两者的性能差异 不重要。

【讨论】:

  • 在现代架构上,分支预测器以接近零的开销吃掉空检查。
  • @280Z28 准确地说,一些现代平台(如果我没记错的话,PlayStation 3 会这样做)消除了分支预测,从而以更难编写程序的代价获得更好的性能
  • @Rune FS:在 ARM 上,检查是通过有条件执行的指令实现的。在 Cell 的 SPU 上,您没有分支预测,但由于其他几个问题,如果您计划在 SPU 上执行托管代码,您应该主要在非空类型上操作。实际上,我为 SPU 编写了一个概念 JIT,它专注于少数对高性能计算有用的数据类型,并省略了运行时空引用检查以支持静态分析(Contracts 库)。
  • @SamHarwell - ...除了污染分支预测器和指令缓存。
【解决方案2】:

除了 asstander 所说的之外,您的问题表明对实例方法的作用存在误解。不管函数是否是静态的,内存中只有一个的函数代码副本。非静态方法必须通过对象调用,但对象不携带自己的私有方法副本。所以静态和非静态方法的内存使用实际上是相同的,正如其他人所指出的,性能特征几乎相同。

但是,

非静态成员变量对于您创建的每个对象确实是单独存在的。但担心内存使用几乎总是浪费时间,除非您的程序中确实存在与内存相关的问题。

【讨论】:

  • "不管函数是不是静态的,内存中只有一份函数代码。"谢谢,我不确定。
  • 一个非静态方法将this 作为隐藏参数传入,因此有人可能会狡辩说它使用了更多的堆栈空间。不过,这似乎并不特别重要。
  • @Steven - 如果您将该方法转换为静态方法,则它需要有一个显式的this 参数。
  • @Earwicker:没错。通常,此类方法首先不适合转换为静态方法。
  • 一条非常关键的信息并不那么明显 - A non-static method has to be called through an object, but the object does not carry its own private copy of the method.。很高兴你提到。 +1。
【解决方案3】:

这有点离题,但同样重要。

staticinstance 方法的选择不应基于执行时间(这似乎无关紧要)。它应该基于方法是否对对象进行操作。例如,所有 Math.* 方法都是静态的,而例如(大多数) String.* 方法是实例,因为它们对 String 实例进行操作。我的个人理念:一个好的设计应该弥补可能在其他地方节省的几个周期

关于这个主题的另一种观点:我最近和一个人一起工作,他被告知静态方法是邪恶的,因为它们把我们带回到了过程编程的黑暗时代,因此应该不惜一切代价避免。这导致了一些奇怪的类示例,这些示例需要实例才能访问对对象内部完全不感兴趣的方法。

唷,从我的壁炉里得到它的感觉真好。

【讨论】:

  • 简单规则:如果方法或属性不访问任何实例状态(this 及其成员),它可能应该是静态的。
  • -1 因为我讨厌那些有正当优化/性能问题的人只是被告知“不要这样做”。有时微优化确实很重要。
  • 偶尔,我喜欢在非静态类中使用小的私有静态函数,这样我可以通过关键字知道该方法不会直接改变非静态实例变量。但是我通常只在方法开始时不接触实例变量时才添加静态关键字。
  • 嗯,他对涉及优化的问题是正确的。避免过早的优化是一个很好的建议,但是人们在给出它时会有一个触发因素。不幸的是,谈论“过早优化”有多糟糕,并没有给我关于我提出的问题的新信息。 “过早的”这个词告诉你,在某些时候优化可能是必要的。如果您连续调用了数百万次并且没有触及实例变量的方法出现性能问题。将其声明为静态可能是有意义的,主要是为了样式,但也为了优化。
  • @dsimcha,我完全同意。微优化有时确实很重要。但是,我在 C#/.Net 等高级语言/环境中(在大多数情况下也适用于嵌入式/低级环境)中开发的经验是,强大的设计更为重要。这当然是我个人的经历,但我相信很多程序员都有相同的经历。
【解决方案4】:

好的答案 - 基本上没关系,这是几乎所有此类问题的答案。即使它确实有所作为 - 如果您的程序的执行时间花费一美元,这种问题可能会花费几分之一美分,并且很可能还有其他事情@ 987654321@.

【讨论】:

    【解决方案5】:

    MeasureIt 可以肯定,但您会发现,除非您正在创建一个覆盖全球的超大容量事务处理超级计算集群,否则它不会有明显的差异。

    【讨论】:

      猜你喜欢
      • 2011-01-16
      • 2011-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      相关资源
      最近更新 更多