首页 / 知识
关于.net:密封类真的能带来性能上的好处吗?
2023-04-11 16:04:00

Do sealed classes really offer performance Benefits?我遇到了很多优化技巧,这些技巧说您应该将类标记为已密封,以获得更多的性能优势。 我进行了一些测试以检查性能差异,但没有发现。 难道我做错了什么? 我是否错过了密封类会带来更好结果的情况? 有没有人进行测试并发现差异? 帮我学习:) 答案是否定的,密封类的性能不会比非密封类好。
问题归结于
不幸的是
结构使用 有关更多信息,请参见此问题: 通话和通话 JITter有时会在密封类中使用对方法的非虚拟调用,因为无法进一步扩展它们。 关于调用类型,虚拟/非虚拟,有复杂的规则,我不了解它们,因此我无法真正为您概述它们,但是如果您搜索密封类和虚拟方法,则可能会找到有关该主题的文章。 请注意,您将从此优化级别获得的任何类型的性能收益都应视为最后解决方案,始终在算法级别进行优化,然后再在代码级别进行优化。 这是一个提到此的链接:在密封关键字上乱逛 更新:从.NET Core 2.0和.NET Desktop 4.7.1开始,CLR现在支持虚拟化。它可以采用密封类中的方法,并用直接调用替换虚拟调用-如果可以确定这样做是安全的,它也可以对非密封类执行此操作。 在这种情况下(CLR无法以其他方式检测到安全性的密封类),密封类实际上应该提供某种性能优势。 就是说,除非您已经分析了代码并确定自己处在被称为数百万次的热路径中,否则我认为不必担心。 https://blogs.msdn.microsoft.com/dotnet/2017/06/29/performance-improvements-in-ryujit-in-net-core-and-net-framework/ 原始答案: 我编写了以下测试程序,然后使用Reflector对其进行了反编译,以查看发出了什么MSIL代码。
在所有情况下,C#编译器(Visual Studio 2010在Release构建配置中)发出相同的MSIL,如下所示:
人们经常说密封的性能优势的原因是编译器知道该类未被覆盖,因此可以使用 我的下一个想法是,即使MSIL是相同的,也许JIT编译器也会以不同方式对待密封类? 我在Visual Studio调试器下运行发行版,并查看了反编译的x86输出。在这两种情况下,x86代码都是相同的,除了类名和函数内存地址(当然它们必须不同)之外。这里是
然后,我认为也许在调试器下运行会导致其执行不太积极的优化? 然后,我在任何调试环境之外都运行了一个独立的发行版可执行文件,并在程序完成后使用WinDBG + SOS进行了插入,并查看了JIT编译的x86代码的废止。
从下面的代码中可以看到,在调试器外部运行时,JIT编译器更具攻击性,并且将 这是在调用普通类时的情况:
与密封类:
对我来说,这提供了有力的证据,证明在密封类和非密封类上的调用方法之间不会有任何性能改进……我想我现在很高兴:-) 据我所知,不能保证性能的提高。但是在某些特定条件下使用密??封方法可以降低性能损失。 (密封类使所有方法都被密封。) 但这取决于编译器的实现和执行环境。 细节 许多现代CPU使用长的流水线结构来提高性能。因为CPU的速度比内存快得多,所以CPU必须从内存中预取代码以加速管线。如果未在适当的时间准备好代码,则管道将处于空闲状态。 有一个称为动态调度的大障碍会破坏此"预取"优化。您可以将其理解为只是条件分支。
在这种情况下,CPU无法预取要执行的下一个代码,因为在条件解决之前,下一个代码位置是未知的。因此,这使危险导致管道闲置。而且,通常,闲置时的性能损失是巨大的。 在方法重写的情况下也会发生类似的事情。编译器可以为当前方法调用确定适当的方法重写,但是有时这是不可能的。在这种情况下,只能在运行时确定适当的方法。这也是动态调度的情况,并且动态类型语言的主要原因通常比静态类型语言慢。 一些CPU(包括最近的Intel x86芯片)使用一种称为推测执行的技术来利用流水线,即使在这种情况下也是如此。只需预取执行路径之一即可。但是这项技术的命中率不是很高。投机失败会导致管道停顿,这也会造成巨大的性能损失。 (这完全是由CPU实现的。某些移动CPU被称为没有这种优化以节省能源)
基本上,C#是静态编译的语言。但不总是。我不知道确切的条件,这完全取决于编译器的实现。如果方法标记为 这个答案(为什么处理排序数组比未排序数组快?)描述了分支预测好得多。
将类标记为
在某些情况下,
在我看来,如果JIT知道类还没有任何子类(尚未),它应该能够对 JIT方面有些赌博,因为如果以后加载子类,则JIT将不得不丢弃该机器代码并再次编译该代码,从而发出真实的虚拟调用。我的猜测是,这在实践中并不经常发生。 (是的,VM设计人员确实确实在积极追求这些微小的性能优势。) <题外话>
我讨厌密封班。即使性能优势惊人(我对此表示怀疑),它们也会通过防止通过继承进行重用而破坏面向对象的模型。例如,Thread类是密封的。虽然我可以看到人们可能希望线程尽可能高效,但我也可以想象能够将Thread子类化的巨大好处。 示例:SafeThread必须包装Thread类,因为Thread是密封的,并且没有IThread接口。 SafeThread会自动捕获线程上未处理的异常,这些异常在Thread类中完全丢失。 [并且不,未处理的异常事件不会在辅助线程中拾取未处理的异常]。 off-topic-rant> 我认为"密封"类是正常情况,我总是有理由省略"密封"关键字。 对我来说,最重要的原因是: a)更好的编译时检查(在编译时,不仅在运行时,还将检测到未实现的接口的广播) 并且,首要原因: b)这样不可能滥用我的课程 我希望微软能够使"密封"成为标准,而不是"未密封"。 密封的类应可提高性能。由于无法派生密封类,因此任何虚拟成员都可以变成非虚拟成员。 当然,我们说的是很小的收获。除非剖析表明存在问题,否则我不会将一个类标记为仅密封以提高性能。 如果JIT Optimizer可以内联调用,否则密封类将至少快一点,但是有时可以更快一些。因此,在通常被称为内联的方法足够小的地方,绝对可以考虑密封该类。 但是,密封类的最好理由是说"我没有将其设计为从继承而来的,因此,我不会通过假定它是这样设计而让您感到厌倦的,因此,我不会通过锁定到一个实现中来烧自己,因为我让您从中获取它。" 我知道这里有些人说他们讨厌密封类,因为他们希望有机会从任何东西中派生……但这通常不是最可维护的选择……因为将类暴露给派生不仅将您暴露在外,还会使您陷入困境那。这类似于说"我讨厌有私人成员的课程……我经常无法使课程做我想要的事情,因为我没有访问权限。"封装很重要...密封是封装的一种形式。 @Vaibhav,您执行了哪种测试来衡量性能? 我猜想人们将不得不使用Rotor并深入CLI,并了解密封类如何提高性能。
运行此代码,您将看到密封类快2倍:
输出: |
最新内容
相关内容
关于Windows:如何从磁盘获得良好的
关于Windows:如何从磁盘获得良好的并发读取性能,关于Windows:如何从磁盘获得良好的并发读取性能,跟进,自己的,有什么,答案,How to obta关于.net:引发异常的性能注意事项
关于.net:引发异常的性能注意事项,关于.net:引发异常的性能注意事项,性能,类型,是一个,这是,Performance Considerations for throwing关于性能:C ++中的CPU节流
关于性能:C ++中的CPU节流,关于性能:C ++中的CPU节流,线程,设置,负载,计算,CPU throttling in C++我只是想知道是否有一种优雅的方法来在性能开始下降之前,MySQL数据库能
在性能开始下降之前,MySQL数据库能达到多少?,在性能开始下降之前,MySQL数据库能达到多少?,性能,数据库,数量,什么时候开始,How big can a关于性能:Python中最有效的图形数据
关于性能:Python中最有效的图形数据结构是什么?,关于性能:Python中最有效的图形数据结构是什么?,节点,数据,边缘,应于,What is the most关于性能:前10000个质数最有效的代
关于性能:前10000个质数最有效的代码?,关于性能:前10000个质数最有效的代码?,想打,您的,代码,质数,Most efficient code for the first 1一些编写高性能HTML应用的建议
一些编写高性能HTML应用的建议,一些,编写,高性能,HTML,应,用的,建议,你,怎么,,你怎么能提高网页性能? 大多数开发者会通过JavaScrJS性能优化createDocumentFragment
JS性能优化createDocumentFragment,性能,优化,createDocumentFragment,性能,优化,,JS性能优化createDocumentFragment我们用原生JSJS性能优化之FOR循环
JS性能优化之FOR循环,性能,优化,之,FOR,循环,性能,优化,之,FOR,循环,,JS性能优化 之 FOR循环1. 最最常规写法,没有任何不妥for (var52套JAVA架构师Spring、微服务、高
52套JAVA架构师Spring、微服务、高并发、分布式、性能调优、高可用,52套JAVA架构师Spring、微服务、高并发、分布式、性能调优、高关于性能:获得π值的最快方法是什么
关于性能:获得π值的最快方法是什么?,关于性能:获得π值的最快方法是什么?,方法,常量,涉及,最快,What is the fastest way to get the va