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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12279438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 22:44:19  来源:igfitidea点击:

Performance of static methods vs instance methods

c#performancestatic-methodsil

提问by Bernie White

My question is relating to the performance characteristics of static methods vs instance methods and their scalability. Assume for this scenario that all class definitions are in a single assembly and that multiple discrete pointer types are required.

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

Consider:

考虑:

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

The above classes represent a helper style pattern.

上面的类代表了一个辅助样式模式。

In an instance class, resolving the instance method take a moment to do as oppose to StaticClass.

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

My questions are:

我的问题是:

  1. When keeping state is not a concern (no fields or properties are required), is it always better to use a static class?

  2. Where there is a considerable number of these static class definitions (say 100 for example, with a number of static methods each) will this affect execution performance or memory consumption negatively as compared with the same number of instance class definitions?

  3. When another method within the same instance class is called, does the instance resolution still occur? For example using the [this] keyword like this.DoOperation2("abc")from within DoOperation1of the same instance.

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

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

  3. 当调用同一个实例类中的另一个方法时,是否仍然发生实例解析?例如使用[此]关键字等this.DoOperation2("abc")从内DoOperation1相同的实例的。

采纳答案by Jon Hanna

In theory, a static method should perform slightly better than an instance method, all other things being equal, because of the extra hidden thisparameter.

理论上,由于额外的隐藏this参数,静态方法的性能应该比实例方法稍好,其他所有条件都相同。

In practice, this makes so little difference that it'll be hidden in the noise of various compiler decisions. (Hence two people could "prove" one better than the other with disagreeing results). Not least since the thisis normally passed in a register and is often in that register to begin with.

在实践中,这几乎没有什么区别,以至于它会隐藏在各种编译器决策的噪音中。(因此,两个人可以“证明”一个比另一个更好的结果不一致)。尤其是因为this通常在寄存器中传递并且通常在该寄存器中开始。

This last point means that in theory, we should expect a static method that takes an object as a parameter and does something with it to be slightly less good than the equivalent as an instance on that same object. Again though, the difference is so slight that if you tried to measure it you'd probably end up measuring some other compiler decision. (Especially since the likelihood if that reference being in a register the whole time is quite high too).

最后一点意味着,从理论上讲,我们应该期待一个静态方法,它接受一个对象作为参数并用它做一些事情,比作为同一对象上的实例的等效方法稍差。尽管如此,差异是如此微小,以至于如果您试图衡量它,您最终可能会衡量其他一些编译器决策。(特别是因为该引用始终在寄存器中的可能性也很高)。

The real performance differences will come down to whether you've artificially got objects in memory to do something that should naturally be static, or you're tangling up chains of object-passing in complicated ways to do what should naturally be instance.

真正的性能差异将归结为您是否在内存中人为地让对象做一些自然应该是静态的事情,或者您是否正在以复杂的方式纠缠对象传递链来做自然应该是实例的事​​情。

Hence for number 1. When keeping state isn't a concern, it's always better to be static, because that's what static is for. It's not a performance concern, though there is an overall rule of playing nicely with compiler optimisations - it's more likely that someone went to the effort of optimising cases that come up with normal use than those which come up with strange use.

因此对于数字 1。当保持状态不是问题时,静态总是更好,因为这就是 static 的作用。这不是一个性能问题,尽管有一个很好地使用编译器优化的总体规则 - 更有可能有人去优化正常使用的情况而不是那些奇怪使用的情况。

Number 2. Makes no difference. There's a certain amount of per-class cost for each member it terms of both how much metadata there is, how much code there is in the actual DLL or EXE file, and how much jitted code there'll be. This is the same whether it's instance or static.

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

With item 3, thisis as thisdoes. However note:

对于第 3 项,this也是this如此。不过请注意:

  1. The thisparameter is passed in a particular register. When calling an instance method within the same class, it'll likely be in that register already (unless it was stashed and the register used for some reason) and hence there is no action required to set the thisto what it needs to be set to. This applies to a certain extent to e.g. the first two parameters to the method being the first two parameters of a call it makes.

  2. Since it'll be clear that thisisn't null, this may be used to optimise calls in some cases.

  3. Since it'll be clear that thisisn't null, this may make inlined method calls more efficient again, as the code produced to fake the method call can omit some null-checks it might need anyway.

  4. That said, null checks are cheap!

  1. this参数在特定寄存器中传递。在同一个类中调用实例方法时,它很可能已经在该寄存器中(除非它被隐藏并且由于某种原因使用了该寄存器),因此无需采取任何措施将 设置为this需要设置的内容. 这在一定程度上适用于例如方法的前两个参数是它进行的调用的前两个参数。

  2. 由于很明显它this不为空,因此在某些情况下这可用于优化调用。

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

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

It is worth noting that generic static methods acting on an object, rather than instance methods, can reduce some of the costs discussed at http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-the-associated-overheads/in the case where that given static isn't called for a given type. As he puts it "As an aside, it turns out that extension methods are a great way to make generic abstractions more pay-for-play."

值得注意的是,作用于对象的泛型静态方法,而不是实例方法,可以降低http://joeduffyblog.com/2011/10/23/on-generics-and-some-of- 中讨论的一些成本the-related-overheads/在给定类型没有调用给定静态的情况下。正如他所说:“顺便说一句,事实证明,扩展方法是使泛型抽象更具性价比的好方法。”

However, note that this relates only to the instantiation of other types used by the method, that don't otherwise exist. As such, it really doesn't apply to a lot of cases (some other instance method used that type, some other code somewhere else used that type).

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

Summary:

概括:

  1. Mostly the performance costs of instance vs static are below negligible.
  2. What costs there are will generally come where you abuse static for instance or vice-versa. If you don't make it part of your decision between static and instance, you are more likely to get the correct result.
  3. There are rare cases where static generic methods in another type result in fewer types being created, than instance generic methods, that can make it sometimeshave a small benefit to turn rarely used (and "rarely" refers to which types it's used with in the lifetime of the application, not how often it's called). Once you get what he's talking about in that article you'll see that it's 100% irrelevant to most static-vs-instance decisions anyway. Edit: And it mostly only has that cost with ngen, not with jitted code.
  1. 大多数情况下,实例与静态的性能成本低于可以忽略不计。
  2. 例如,当您滥用静态时,通常会产生什么成本,反之亦然。如果您不将它作为您在静态和实例之间的决定的一部分,您更有可能得到正确的结果。
  3. 在极少数情况下,另一种类型中的静态泛型方法会导致创建的类型少于实例泛型方法,这有时会使其很少使用(并且“很少”指的是它在应用程序的生命周期,而不是调用它的频率)。一旦你明白了他在那篇文章中谈论的内容,你就会发现它与大多数静态与实例决策 100% 无关。编辑:它主要只有 ngen 的成本,而不是 jitted 代码。

Edit: A note on just how cheap null-checks are (which I claimed above). Most null-checks in .NET don't check for null at all, rather they continue what they were going to do with the assumption that it'll work, and if a access exception happens it gets turned into a NullReferenceException. As such, mostly when conceptually the C# code involves a null-check because it's accessing an instance member, the cost if it succeeds is actually zero. An exception would be some inlined calls, (because they want to behave as if they called an instance member) and they just hit a field to trigger the same behaviour, so they are also very cheap, and they can still often be left out anyway (e.g. if the first step in the method involved accessing a field as it was).

编辑:关于空检查有多便宜的注释(我在上面声称)。.NET 中的大多数空检查根本不检查空值,而是继续他们将要做的事情,假设它会起作用,并且如果发生访问异常,它会变成NullReferenceException. 因此,主要是当 C# 代码在概念上涉及空检查时,因为它正在访问实例成员,如果它成功,成本实际上为零。一个例外是一些内联调用,(因为他们想要表现得好像他们调用了一个实例成员)并且他们只是点击了一个字段来触发相同的行为,所以他们也非常便宜,而且他们仍然经常被排除在外(例如,如果该方法的第一步涉及按原样访问字段)。

回答by Tigran

When keeping state is not a concern (no fields or properties are required), is it always better to use a static class?

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

I would say, yes. As declaring something staticyou declare an intentof stateless execution (it's not mandatory, but an intent of something one would expect)

我会说,是的。在声明某事时,static您声明了无状态执行的意图(这不是强制性的,而是人们期望的意图)

Where there is a considerable number of these static classes (say 100 for instance, with a number of static methods each) will this affect execution performance or memory consumption negatively as compared with the same number of instance classes?

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

Don't think so, unless you're sure that static classes are reallystetless, cause if not it's easy mess up memory allocations and get memory leaks.

不要这么认为,除非您确定静态类确实无障碍,否则很容易弄乱内存分配并导致内存泄漏。

When the [this] keyword is used to call another method within the same instance class, does the instance resolution still occur?

当使用[this]关键字调用同一个实例类中的另一个方法时,是否还会出现实例解析?

Not sure, about thispoint (this is a purely implementation detail of CLR), but think yes.

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

回答by burning_LEGION

static methods are faster but less OOP, if you'll be use design patterns static method likely bad code, to write business logic better without static, common functions like file reading, WebRequest etc better realize as static... you questions have no universal answer

静态方法更快但OOP更少,如果您将使用设计模式静态方法可能是糟糕的代码,在没有静态的情况下更好地编写业务逻辑,文件读取,WebRequest等常用功能更好地实现为静态...您的问题没有通用性回答