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

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

考虑:

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. } 

上面的类表示一个帮助器样式。

在一个实例类中,parsing实例方法需要一点时间来做与StaticClass相反的事情。

我的问题是:

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

  2. 如果有相当数量的这些静态类定义(比如说每个静态方法有100个),那么与相同数量的实例类定义相比,这会不会影响执行性能或内存消耗?

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

从理论上讲,静态方法应该比实例方法稍微好一点,其他所有的东西都是相等的,因为this参数是额外的。

在实践中,这个差别很小,它会隐藏在各种编译器决定的噪声中。 (因此,两个人可以“certificate”一个比另一个有不同的结果)。 尤其是因为this通常是通过一个注册,并通常在该登记册开始。

最后一点意味着理论上我们应该期待一个静态方法,它将一个对象作为一个参数,并用它做一些事情,使它比同一个对象上的实例稍微逊色一些。 虽然如此,差异是如此微小,如果你试图测量它,你可能最终会测量一些其他编译器的决定。 (尤其是如果那个参考文献在整个时间里的可能性也相当高)。

真正的性能差异将归结为你是否已经人为地将内存中的对象做成自然是静态的东西,或者你正在以复杂的方式纠结对象传递的链条,以做自然而然的事情。

因此,对于数字1.当保持状态不是一个问题时,最好是静态的, 因为这是静态的 。 这不是一个性能问题,尽pipe总体规则是编译器优化的一个很好的玩法 – 更有可能有人去优化那些正常使用的例子,而不是那些使用奇怪的例子。

数字2没有区别。 对于每个成员来说,每个成员都有一定数量的成本,它包括多less元数据,实际的DLL或EXE文件中有多less代码,以及多less代码会存在。 无论是实例还是静态,这都是一样的。

对于第3项, thisthis 。 但是注意:

  1. this参数被传入一个特定的寄存器。 当在同一个类中调用一个实例方法时,它可能已经在这个寄存器中了(除非它被隐藏,并且因为某种原因使用了这个寄存器),因此不需要采取任何行动来设置它需要设置的值至。 这在某种程度上适用于例如该方法的前两个参数是它所做的呼叫的前两个参数。

  2. 由于很明显this不是空的,在某些情况下,这可能被用来优化呼叫。

  3. 由于显然this不是null,这可能会使内联方法调用再次更有效,因为生成的用于伪造方法调用的代码可能会忽略它可能需要的一些空值检查。

  4. 这就是说,空检查便宜!

值得注意的是,对一个对象而不是实例方法进行操作的generics静态方法,可以减less在这个案例中讨论的一些成本( http://www.bluebytesoftware.com/blog/2011/10/23/OnGenericsAndSomeOfTheAssociatedOverheads.aspx)给定的静态不被调用给定的types。; 正如他所说的那样,“事实certificate,扩展方法是使generics抽象更多按需付费的好方法”。

但是,请注意,这只涉及该方法使用的其他types的实例,而这些实例不存在。 因此,它确实不适用于很多情况(某些其他实例方法使用该types,某些其他代码使用该types)。

概要:

  1. 实例与静态的性能成本大多低于可忽略的程度。
  2. 一般来说,你会滥用静态的地方,反之亦然。 如果你不把它作为静态和实例之间的决定的一部分,你更可能得到正确的结果。
  3. 在极less数情况下,另一种types的静态generics方法导致创build的types较less,而不是实例generics方法,这可能会使其有时很less使用很less使用的好处(而“很less”是指使用哪种types的应用程序的生命周期,而不是被称为)。 一旦你在那篇文章中得到他所说的内容,你就会发现它与大多数静态与实例决策无关。 编辑:它大多只有与ngen的成本,而不是jitted的代码。

编辑:关于如何便宜的空检查(我上面声称)。 在.NET中大多数的空检查不会检查null,而是继续他们将要做的事情,假设它会工作,如果发生访问exception,它会变成NullReferenceException 。 因此,大多数情况下,当C#代码在概念上涉及一个空检查,因为它正在访问一个实例成员,如果它成功的话,成本实际上是零。 一个例外是一些内联调用(因为他们想performance得好像他们叫做实例成员一样),他们只是碰到一个领域触发相同的行为,所以他们也很便宜,而且仍然经常被忽略(例如,如果方法的第一步涉及访问一个字段,那就是)。

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

我会说,是的。 作为声明static东西,你声明了无状态执行的意图 (这不是强制性的,而是人们所期望的意图)

如果有相当数量的这些静态类(比如说每个静态方法有100个),那么与相同数量的实例类相比,这会不会影响执行性能或内存消耗?

不要这样认为,除非你确定静态类是真的没有,否则很容易搞乱内存分配和内存泄漏。

当使用[this]关键字调用同一个实例类中的另一个方法时,实例parsing是否仍然发生?

不确定,关于一点(这是CLR的一个纯粹的实现细节),但认为是的。

静态方法更快但更less的OOP,如果你将使用devise模式静态方法可能不好的代码,更好地编写业务逻辑没有静态,像文件阅读,WebRequest等常见的function更好地实现静态…你的问题没有通用回答