C#generics是否具有性能优势?
我有许多代表各种实体的数据类。
哪一个更好:使用generics和接口编写generics类(比如打印或输出XML),或者编写一个单独的类来处理每个数据类?
是否有performance收益或其他利益(除了节省我分开的课程时间)?
使用generics会带来显着的性能优势 – 您不再需要装箱和拆箱 。 与开发自己的课程相比,这是一个硬币投掷(硬币的一面比另一面更重)。 只有当你认为自己可以超越框架的作者时,才能自己动手。
不仅是的,而且是肯定的。 我不相信他们能做出多大的差别。 我们在重写了一小部分将ArrayLists和HashTables用于generics的核心代码后,在VistaDB中进行了testing。 速度提高了250%以上。
阅读我的博客,了解我们对generics与弱型集合进行的testing。 结果让我们大跌眼镜。
我已经开始将大量使用弱types集合的旧代码重写成强types集合。 我对ADO.NET接口的一个最大的处理就是他们不公开更强大的数据input和输出方式。 从物体到背部的投射时间是大批量应用中的绝对杀手。
强types的另一个副作用是你经常会在代码中发现弱types的引用问题。 我们发现通过在某些情况下实施结构以避免对GC施加压力,我们可以进一步加快我们的代码。 将此与powershell打字相结合以获得最佳的速度提升。
有时你必须在dot net运行时使用弱types的接口。 尽可能寻找保持强types的方法。 对于非平凡的应用程序来说,这确实会使性能发生巨大的变化。
C#中的generics从CLR的angular度来看是真正的genericstypes。 generics类和完全相同的特定类之间不应该有任何根本的区别。 这与Java Generics不同,后者更多的是自动化的types转换,或者是在编译时扩展的C ++模板。
这里有一篇很好的论文,讲述了基本devise: “ . NET通用语言运行时generics的devise和实现” 。
如果您为特定任务手写类,您可以优化某些方面,您需要通过genericstypes的接口进行额外的绕行。
总之,可能会有性能优势,但我会先推荐通用解决scheme,然后根据需要进行优化。 如果您希望实例化具有许多不同types的generics,则尤其如此。
我做了一些关于ArrayList与generics列表的一个简单的基准testing:一个不同的问题: generics与数组列表 ,你的里程会有所不同,但generics列表比ArrayList快4.7倍。
所以是的,拳击/拆箱是非常关键的, 如果你正在做很多的操作。 如果你正在做简单的CRUD的东西,我不会担心它。
generics是参数化代码和避免重复的一种方法。 看看你的程序描述和你写一个单独的类来处理每一个数据对象的想法,我会倾向于generics。 拥有一个类来处理许多数据对象,而不是许多同类事物的类,可以提高性能。 当然,您的性能(以改变代码的能力来衡量)通常比计算机性能更重要。 🙂
据微软称,generics比铸造(装箱/拆箱原语)要快。 他们还声称,generics提供了比参考types更好的性能, 这似乎是不真实的 (没有人能certificate这一点)。
Tony Northrup(MCTS 70-536:应用程序开发基金会的合着者)在同一本书中陈述了以下内容:
我一直无法重现generics的性能优势。 然而,据微软称,generics要比使用铸造更快。 在实践中,铸造certificate比使用通用要快几倍。 但是,您可能不会注意到应用程序中的性能差异。 (我的testing超过100,000次迭代只花了几秒钟。)所以你仍然应该使用generics,因为它们是types安全的。
我还没有能够重现这种与generics相比的性能优势,而不是参考types之间的相互转换 – 所以我会说性能增益“应该”比“重要”更大。
如果将通用列表(例如)与特定的列表进行比较,那么所使用的types差异很小,JIT编译器的结果几乎相同。
如果您将通用列表与对象列表进行比较,那么对通用列表有很大好处 – 对值types不进行装箱/拆箱,对引用types不进行types检查。
.net库中的generics集合类也进行了大量优化,你不可能自己做的更好。
generics更快!
我还发现Tony Northrup在他的书中写了关于仿制药和非仿制药performance的错误。
我在我的博客上写了这个: http : //andriybuday.blogspot.com/2010/01/generics-performance-vs-non-generics.html
这里是一个伟大的文章,作者比较generics和非generics的性能:
nayyeri.net/use-generics-to-improve-performance
如果您正在考虑调用某个接口上的方法来执行其工作的generics类,那么它将比使用已知types的特定类慢,因为调用接口方法比(非虚拟)函数调用要慢。
当然,除非代码是性能关键stream程的缓慢部分,否则您应该关注清楚。
在generics集合与boxing等的情况下,像ArrayList这样的较老的集合,generics是一个性能的胜利。 但在绝大多数情况下,这不是generics最重要的好处。 我认为有两件事情有更大的好处:
- types安全。
- 自我logging更可读。
generics促进了types安全,迫使更加均匀的收集。 想象一下当你期待一个int时,在一个string上磕磕绊绊。 哎哟。
通用集合也更自我logging。 考虑下面的两个集合:
ArrayList listOfNames = new ArrayList(); List<NameType> listOfNames = new List<NameType>();
读取你可能认为的第一行listOfNames是一个string列表。 错误! 它实际上是存储NameTypetypes的对象。 第二个例子不仅强制types必须是NameType(或后代),而且代码更具可读性。 我马上知道,我需要去查找TypeName,并通过查看代码学习如何使用它。
我在StackOverflow上看到了很多这样的“x比y好”的问题。 这里的问题是非常公平的,而且事实certificate,仿制药是一种胜利,任何你皮肤的猫。 但是在一天结束的时候,重点是向用户提供一些有用的东西。 确保您的应用程序需要能够执行,但也不需要崩溃,而且您需要能够快速响应错误和function请求。 我认为你可以看到最后两点与generics集合的types安全性和代码可读性是如何相关的。 如果是相反的情况,如果ArrayList胜过List <>,那么除非性能差异显着,否则我可能仍然采用List <>实现。
就性能而言(总的来说),我敢打赌,你将在职业生涯中发现这些领域的大部分性能瓶颈:
- 数据库或数据库查询devise不当(包括索引等),
- 糟糕的内存pipe理(忘记调用处理,深层堆栈,持久对象等),
- 不正确的线程pipe理(太多的线程,不能在桌面应用程序的后台线程上调用IO等),
- 糟糕的IOdevise
这些都不是单线解决scheme。 我们作为程序员,工程师和极客们都想知道所有酷炫的小表演技巧。 但重要的是我们保持眼球。 我相信在上面提到的四个方面关注良好的devise和编程实践将会进一步导致更多的问题,而不是担心微小的性能提升。
在MSDN上也可以看到Rico Mariani的博客:
http://blogs.msdn.com/ricom/archive/2005/08/26/456879.aspx
Q1:哪个更快?
generics版本相当快,见下文。
这篇文章有点旧,但是给出了细节。
不仅可以避免使用装箱,而且由于底层实现的改变,generics实现比具有引用types的非generics实现要快一些。
原件是根据特定的扩展模型devise的。 这个模型从来没有真正被使用(反正也是一个坏主意),但是devise决定迫使一些方法是虚拟的,因此是不可理解的(基于当前和过去的JIT优化)。
这个决定在较新的课程中得到了纠正,但是如果不是一个潜在的二元重大改变,就不能在旧的课程中改变。
另外,通过foreach <>(而不是IList <>)迭代通过ArrayList的枚举器需要堆分配更快。 诚然,这确实导致了一个晦涩的错误