静态方法与实例方法的性能(Performance of static methods vs instance methods)

编程入门 行业动态 更新时间:2024-10-20 05:30:59
静态方法与实例方法的性能(Performance of static methods vs instance methods)

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

考虑:

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.DoOperation2("abc")这样的关键字。

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.

My questions are:

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

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?

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 DoOperation1 of the same instance.

最满意答案

理论上,一个静态方法应该比一个实例方法稍好一点,所有其他的事情是相等的,因为this参数是额外的隐藏的。

实际上,这使得它几乎不会被隐藏在各种编译器决策的噪点中。 (因此,两个人可以通过不同意的结果“证明”一个比另一个更好)。 这不仅仅是因为this通常是通过一个注册表,通常在该注册表开始。

最后一点意味着在理论上,我们应该期望一个静态方法,它将一个对象作为一个参数,并且做一些与之相同的对象作为同一对象的实例。 再次,区别是如此之小,如果你试图测量它,你可能会最终测量一些其他编译器的决定。 (特别是因为如果该参考在注册表中的可能性,整个时间也是相当高的)。

真正的性能差异将归结为你是否人为地拥有记忆中的对象来做一些自然应该是静态的东西,或者你以复杂的方式纠缠对象传递链,做自然应该是实例。

因此,对于第1号。当保持状态不是一个问题时,总是最好是静态的, 因为这是静态的 。 这不是一个性能问题,尽管有一个整体规则可以很好地与编译器优化 - 很有可能是有人去努力优化出现正常使用的情况,而不是出现奇怪的使用。

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

与项目3, this是this 。 但是请注意:

该参数在特定寄存器中传递。 当调用同一个类中的一个实例方法时,它很可能已经在该寄存器中(除非它由于某些原因而被保留并使用该寄存器),因此无需this操作设置为需要设置的内容至。 这在某种程度上适用于例如该方法的前两个参数是其进行的调用的前两个参数。

由于很明显this不是空的,所以在某些情况下可以用来优化调用。

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

也就是说,零检查便宜!

值得注意的是,作用于对象而不是实例方法的通用静态方法可以减少http://www.bluebytesoftware.com/blog/2011/10/23/OnGenericsAndSomeOfTheAssociatedOverheads.aspx中讨论的一些成本给定静态不给定类型。 正如他所说,“除此之外,原理是扩展方法是使泛型抽象更加付费的好办法。”

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

概要:

大多数情况下,实例与静态的性能成本可忽略不计。 通常情况下,您会滥用静态方式,反之亦然。 如果您不将其作为静态和实例之间的决策的一部分,则更有可能获得正确的结果。 在另一种类型的静态泛型方法中,有少数情况导致创建的类型较少,而不是实例通用方法,这可能使得有时很少使用很少的优点(而且“很少”是指在应用程序的生命周期,而不是多久被调用)。 一旦你得到他在谈论的文章,​​你会看到它与大多数静态vs实例的决定100%无关。 编辑:它主要只有ngen的成本,而不是带有代码。

编辑:一个关于多少便宜的零点检查(我上面声明)的注释。 .NET中的大多数空值检查根本不检查null,而是继续使用它将会工作的假设,如果访问异常发生,它将变成NullReferenceException 。 因此,大多数情况下,C#代码在概念上涉及到空检,因为它访问了一个实例成员,成本如果成功,实际上是零。 一个例外是一些内联调用(因为他们想表现得好像他们调用一个实例成员),并且他们只是打一个字段来触发相同的行为,所以它们也很便宜,而且仍然经常被忽略(例如,如果方法中的第一步涉及访问一个字段)。

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

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 this is normally passed in a register and is often in that register to begin with.

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.

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.

With item 3, this is as this does. However note:

The this parameter 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 this to 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.

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

Since it'll be clear that this isn'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.

That said, null checks are cheap!

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

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:

Mostly the performance costs of instance vs static are below negligible. 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. 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 sometimes have 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.

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

更多推荐

本文发布于:2023-04-29 12:12:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1336333.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:方法   静态   实例   性能   methods

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!