C#Generics有性能优势吗?

时间:2008-09-22 19:32:53

标签: c# .net performance generics

我有许多代表各种实体的数据类。

哪个更好:使用泛型和接口编写泛型类(比如打印或输出XML),或者编写一个单独的类来处理每个数据类?

是否有性能优势或任何其他好处(除了节省我编写单独课程的时间之外)?

12 个答案:

答案 0 :(得分:58)

使用泛型具有显着的性能优势 - 您不再使用boxing and unboxing。与开发自己的课程相比,它是一个抛硬币(硬币的一侧加权比另一侧重)。如果您认为自己可以胜过框架的作者,那么请自己动手。

答案 1 :(得分:20)

不仅是,而是HECK YES。我不相信他们能做出多大的改变。在将一小部分使用ArrayLists和HashTables的核心代码重写为泛型之后,我们在VistaDB中进行了测试。 250%或更多是提高速度。

Read my blog about the testing我们在泛型与弱类型集合上做过。结果引起了我们的注意。

我已经开始重写大量使用弱类型集合的旧代码到强类型集合。 ADO.NET界面最让人印象深刻的一点就是它们没有暴露出更强类型的数据输入和输出方式。从物体到背部的铸造时间是大批量应用中的绝对杀手。

强类型的另一个副作用是您经常会在代码中发现弱类型的引用问题。我们发现在某些情况下通过implementing structs来避免对GC施加压力,我们可以进一步加快代码速度。将此与强力打字相结合,以获得最佳速度提升。

有时您必须在dot net运行时中使用弱类型接口。尽可能地寻找保持强类型的方法。对于非平凡的应用程序来说,它确实在性能上有很大的不同。

答案 2 :(得分:15)

C#中的泛型是CLR角度的真正通用类型。泛型类的性能与完全相同的特定类之间应该没有任何根本区别。这与Java Generics不同,后者更像是需要的自动类型转换或在编译时扩展的C ++模板。

这是一篇很好的论文,有点陈旧,它解释了基本设计: "Design and Implementation of Generics for the .NET Common Language Runtime"

如果您为特定任务手写类,那么您可以通过泛型类型的接口优化某些方面需要额外的弯路。

总之,可能会有性能优势,但我会首先推荐通用解决方案,然后根据需要进行优化。如果您希望使用许多不同类型实例化泛型,则尤其如此。

答案 3 :(得分:7)

我针对不同的问题对ArrayList和通用列表进行了一些简单的基准测试:Generics vs. Array Lists,您的里程会有所不同,但通用列表比ArrayList快4.7倍。

所以是的,装箱/拆箱是关键的,如果你正在做很多操作。如果你正在做简单的CRUD,我不会担心它。

答案 4 :(得分:6)

泛型是参数化代码和避免重复的方法之一。看看你的程序描述和你编写一个单独的类来处理每个数据对象的想法,我会倾向于泛型。让一个单独的类处理许多数据对象,而不是许多做同样事情的类,可以提高您的性能。当然,以改变代码的能力衡量的性能通常比计算机性能更重要。 : - )

答案 5 :(得分:4)

根据微软的说法,Generics比铸造(装箱/拆箱原语)更快。 他们还声称泛型提供的性能比在引用类型之间提供更好的性能,似乎是不真实的(没有人可以证明它)。

Tony Northrup-- MCTS 70-536:应用程序开发基金会的合着者 - 在同一本书中陈述如下:

  

我无法重现   仿制药的性能优势;   然而,根据微软的说法,   泛型比使用更快   铸件。在实践中,铸造证明了   比使用速度快几倍   通用的。但是,你可能不会   注意你的表现差异   应用。 (我的测试超过100,000   迭代只用了几秒钟。)   所以你仍然应该使用泛型   因为它们是类型安全的。

与参考类型之间的转换相比,我无法使用泛型再现这样的性能优势 - 所以我认为性能增益“假定”超过“重要”。

答案 6 :(得分:3)

如果将通用列表(例如)与特定列表进行比较,确切地说是您使用的类型,则差异很小,JIT编译器的结果几乎相同。

如果将通用列表与对象列表进行比较,那么通用列表会有很大的好处 - 没有值类型的装箱/拆箱,也没有类型检查参考类型。

.net库中的泛型集合类也经过了大量优化,你自己也不太可能做得更好。

答案 7 :(得分:3)

泛型更快!

我还发现Tony Northrup在他的书中写了关于泛型和非泛型的性能的错误信息。

我在博客上写过: http://andriybuday.blogspot.com/2010/01/generics-performance-vs-non-generics.html

这是一篇很棒的文章,作者比较了泛型和非泛型的表现:

nayyeri.net/use-generics-to-improve-performance

答案 8 :(得分:2)

如果您正在考虑在某个接口上调用方法来执行其工作的泛型类,那将比使用已知类型的特定类慢,因为调用接口方法比(非虚拟)函数调用慢

当然,除非代码是关键性能流程的缓慢部分,否则您应该集中精力。

答案 9 :(得分:2)

对于通用集合与拳击等人的情况,对于像ArrayList这样的旧集合,泛型是性能上的胜利。但在绝大多数情况下,这不是仿制药最重要的好处。我认为有两件事有更大的好处:

  1. 类型安全。
  2. 自我记录也更具可读性。
  3. 仿制药促进了类型安全,迫使收集更加均匀。想象一下,当你期望一个int时,想象一下你会遇到一个字符串。哎哟。

    通用集合也更加自我记录。考虑下面的两个集合:

    ArrayList listOfNames = new ArrayList();
    List<NameType> listOfNames = new List<NameType>();
    

    读第一行你可能认为listOfNames是一个字符串列表。错误!它实际上存储NameType类型的对象。第二个示例不仅强制类型必须是NameType(或后代),而且代码更具可读性。我立刻就知道我需要找到TypeName并通过查看代码来学习如何使用它。

    我在StackOverflow上看过很多这些“x表现得比y好”的问题。这里的问题是非常公平的,因为事实证明,仿制药是一种赢得任何方式你皮肤猫。但在一天结束时,重点是为用户提供有用的东西。当然,您的应用程序需要能够执行,但它也不需要崩溃,您需要能够快速响应错误和功能请求。我想您可以看到最后两点如何与通用集合的类型安全性和代码可读性相关联。如果是相反的情况,如果ArrayList的性能优于List&lt;&gt;,我可能仍会采用List&lt;&gt;除非绩效差异很大,否则将实施。

    就性能而言(一般而言),我愿意打赌你会在职业生涯中找到这些领域的大部分绩效瓶颈:

    1. 数据库或数据库查询设计不当(包括索引等),
    2. 内存管理不善(忘记调用dispose,深层堆栈,抓住对象太久等),
    3. 线程管理不当(线程太多,不在桌面应用程序的后台线程上调用IO等),
    4. IO设计不佳。
    5. 这些都不是用单线解决方案修复的。我们作为程序员,工程师和极客想要了解所有很酷的小性能技巧。但重要的是我们要注意球。我相信专注于上面提到的四个方面的优秀设计和编程实践将进一步导致远远超过担心小的性能提升。

答案 10 :(得分:2)

在MSDN上也看到Rico Mariani的博客:

http://blogs.msdn.com/ricom/archive/2005/08/26/456879.aspx

  

Q1:哪个更快?

     

泛型版本相当可观   更快,见下文。

文章有点旧,但提供了详细信息。

答案 11 :(得分:0)

由于底层实现的改变,你不仅可以取消装箱,而且通用实施比参考类型的非通用实施更快一些。

原件的设计考虑了特定的扩展模型。这个模型从来没有真正使用过(无论如何都是一个坏主意)但是设计决策迫使一些方法变得虚拟,因而无法使用(基于当前和过去JIT在这方面的优化)。

这个决定在较新的课程中得到了纠正,但如果没有潜在的二元拆分更改,则不能在较旧的课程中进行更改。

另外,通过foreach在List&lt;&gt;上进行迭代由于ArrayList的枚举器需要堆分配,因此(而不是IList&lt;&gt;)更快。不可否认,这确实导致obscure bug