Do sealed classes really offer performance Benefits?
I have come across a lot of optimization tips which say that you should mark your classes as sealed to get extra performance benefits.
I ran some tests to check the performance differential and found none. Am I doing something wrong? Am I missing the case where sealed classes will give better results?
Has anyone run tests and seen a difference?
Help me learn :)
The JITter will sometimes use non-virtual calls to methods in sealed classes since there is no way they can be extended further.
There are complex rules regarding calling type, virtual/nonvirtual, and I don't know them all so I can't really outline them for you, but if you google for sealed classes and virtual methods you might find some articles on the topic.
Note that any kind of performance benefit you would obtain from this level of optimization should be regarded as last-resort, always optimize on the algorithmic level before you optimize on the code-level.
Here's one link mentioning this: Rambling on the sealed keyword
The answer is no, sealed classes do not perform better than non-sealed.
The issue comes down to the call
vs callvirt
IL op codes. Call
is faster than callvirt
, and callvirt
is mainly used when you don't know if the object has been subclassed. So people assume that if you seal a class all the op codes will change from calvirts
to calls
and will be faster.
Unfortunately callvirt
does other things that make it useful too, like checking for null references. This means that even if a class is sealed, the reference might still be null and thus a callvirt
is needed. You can get around this (without needing to seal the class), but it becomes a bit pointless.
Structs use call
because they cannot be subclassed and are never null.
See this question for more information:
Call and callvirt
As I know, there is no guarantee of performance benefit. But there is a chance to decrease performance penalty under some specific condition with sealed method. (sealed class makes all methods to be sealed.)
But it's up to compiler implementation and execution environment.
Details
Many of modern CPUs use long pipeline structure to increase performance. Because CPU is incredibly faster than memory, CPU has to prefetch code from memory to accelerate pipeline. If the code is not ready at proper time, the pipelines will be idle.
There is a big obstacle called dynamic dispatch which disrupts this 'prefetching' optimization. You can understand this as just a conditional branching.
// Value of `v` is unknown,
// and can be resolved only at runtime.
// CPU cannot know code to prefetch,
// so just prefetch one of a() or b().
// This is *speculative execution*.
int v = random();
if (v==1) a();
else b();
CPU cannot prefetch next code to execute in this case because the next code position is unknown until the condition is resolved. So this makes hazard causes pipeline idle. And performance penalty by idle is huge in regular.
Similar thing happen in case of method overriding. Compiler may determine proper method overriding for current method call, but sometimes it's impossible. In this case, proper method can be determined only at runtime. This is also a case of dynamic dispatch, and, a main reason of dynamically-typed languages are generally slower than statically-typed languages.
Some CPU (including recent Intel's x86 chips) uses technique called speculative execution to utilize pipeline even on the situation. Just prefetch one of execution path. But hit rate of this technique is not so high. And speculation failure causes pipeline stall which also makes huge performance penalty. (this is completely by CPU implementation. some mobile CPU is known as does not this kind of optimization to save energy)
Basically, C# is a statically compiled language. But not always. I don't know exact condition and this is entirely up to compiler implementation. Some compilers can eliminate possibility of dynamic dispatch by preventing method overriding if the method is marked as sealed
. Stupid compilers may not. This is the performance benefit of the sealed
.
This answer (Why is it faster to process a sorted array than an unsorted array?) is describing the branch prediction a lot better.
链接地址: http://www.djcxy.com/p/5380.html上一篇: else语句,哪个更快?
下一篇: 密封类真的提供性能好处吗?