限时领|《AI 百问百答》专栏课+实体书(包邮)! 了解详情
写点什么

讨论:泛型是否会对性能产生负面影响

  • 2009-05-30
  • 本文字数:1861 字

    阅读完需:约 6 分钟

正值端午传统节日,在国内知名的.NET 技术社区博客园中进行了一场较为激烈的讨论。讨论话题围绕:.NET 中的泛型是否会影响性能。

飞林沙的一篇文章《从 dynamic 到特性误用》引起了这场讨论。在这片文章中,飞林沙指出 C# 4.0 新增的 dynamic 关键字会对程序性能的影响,呼吁大家仅在合适的时候使用 dynamic 新特性。可能是由于社区中对于 C# 4.0 的新特性还不太关注,这个问题本身的反响不大。反而是文章所引发的一个周边话题引起了网友的兴趣。

在文章的结尾,飞林沙认为太多开发人员并没有了解新特性的优劣就盲目追逐,并举出他所认为的一个泛型错误做法:

……我看到有人在代码中使用 List而不是 ArrayList,我不明白这种做法除了降低性能之外还有什么好处……

文章发表不久,便有网友对此观点产生质疑,认为“泛型是生成新的类型,拿来的效率影响之说”,不过也有网友表示“.NET 的泛型会略微影响效率,跟 C++ 略有些不同”。在 Jeffrey Zhao 发表了一篇性能比较文章之后,围绕这个话题的讨论便由此展开。

Jeffrey Zhao 的文章《泛型真的会降低性能吗?》使用代码来统计常用操作所消耗的时间,试图发现泛型容器对性能的影响。除了.NET 类库中经典的 ArrayList 和 List类型之外,他还编写了最简单的 MyArrayList 和 MyList两个类型,目的是避免其它任何实现方面的细节对性能的影响。对于长度为 100 的容器,各执行 30 万次操作的结果如下表所示:

使用 for 进行下标遍历 使用 foreach 进行遍历 MyArrayList 2,398ms 21,367ms MyList 2,285ms 3,463ms ArrayList 2,282ms 5,187ms List 2,302ms 2,989ms 根据实验结果,Jeffrey Zhao 得出了以下结论:

……泛型的 MyList 性能甚至略比 MyArrayList 有所提高。当然测试的结果其实是互有胜负,但是事实上,MyList 的获胜的次数甚至还略有领先……从结果上已经可以看出,泛型并不会影响性能,而 List的性能也不比 ArrayList 要差……

Jeffrey Zhao 同时呼吁“在有泛型支持的情况下,尽量使用泛型容器。例如使用 List而不是 ArrayList”:

……除了“性能”之外,老赵的还有其他一些理由。例如使用 List的话就可以使用框架内部所定义的各种有用的辅助方法(要知道在.NET 框架中,现在几乎都是在针对 IEnumerable进行开发);而我们平时写程序时,也可以统一的针对泛型编程,如 IList,IEnumerable,不必考虑 List 或 Enumerable 等非泛型元素。

Jeffrey Zhao 的测试结果得到了大部分网友的承认,不过也有部分网友对这个实验的部分做法有所质疑。如开源框架 NBear 的创始人 Teddy Ma 认为 MyArrayList 的 foreach 操作慢的原因在于非泛型的 IEnumerator 内部对于数组使用 Array.GetValue(Int32) 来获取对象,而泛型的 IEnumerator则直接使用数组下标进行访问:

……如果都用 for 而不是 foreach,我想应该非泛型略快一点点。

对此,Jeffrey Zhao 回应道:

……我测试的都是平时的常用操作,黑盒测试,没有故意去走某个特别慢的路径。……看来内部实现的造成问题,可惜我们平时都是用这个做法,因为是框架自带的。

为什么总是说泛型性能会差一些?测试结果都摆在这里了。根据测试结果,就算是下标访问,泛型也不差。……所以结论还是不变,能够用 List就不要用 ArrayList。

稍后又有网友引用了国外网友 Rico Mariani 的文章回复中总结的观点,认为 ArrayList 比 List性能差的原因在于:

  1. ArrayList 中使用了大量的虚方法,.NET 框架设计团队不反对我们继承 ArrayList 实现新的集合类型。这种做法也影响了 JIT 对方法的内联。
  2. ArrayList 的遍历器实现较为复杂,会构造大量的 Enumerator 对象。而在.NET 2.0 中新设计的 List类型简化了这部分代码,获得了较高的性能。

至此,大家基本已经达成共识,ArrayList 性能较差是由于内部实现逻辑的影响,在实际开发过程中使用 List能够获得更好的性能。不过,还是有一些网友“普遍认为”,抛开泛型对值类型装箱 / 拆箱的性能优化,纯粹的泛型容器性能还是会略低于非泛性的 Object 容器。不过,Jeffrey Zhao 新发表的一篇文章似乎从根本上推翻了这个看法。

在《从汇编入手,探究泛型的性能问题》一文中,Jeffrey Zhao 使用 WinDbg 查看了 MyArrayList 和 MyList的下标 get 方法,在 JIT 之后所生成的汇编代码,并加以详细的分析和对比。比较的结果发现,两者除了几个地址不同之外,在执行时所经过的指令几乎完全相同,以此有力地证明了“泛型并不会影响程序性能”。

在问题的讨论过程中也产生了一些额外的话题,例如究竟应该使用 for 和下标访问,还是 foreach 来遍历一个容器,还有一个应用程序是否应该在这样的地方追求性能提升。

您的看法是什么呢?

2009-05-30 20:193742
用户头像

发布了 157 篇内容, 共 59.5 次阅读, 收获喜欢 6 次。

关注

评论

发布
暂无评论
发现更多内容

2021先定个小目标?搞清楚MyCat分片的两种拆分方法和分片规则!

Java 程序员 后端

2021年最新Java后端学习路线,适用于所有想要踏入Java行业的初学者!

Java 程序员 后端

10年Java开发经验,超过500人面试阿里的同学,总结出这108道面试题

Java 程序员 后端

2020最新阿里巴巴必问的200个面试题以及答案,助你斩获阿里offer

Java 程序员 后端

2021最强面试笔记非它莫属:3000字Java面试核心手册(大厂必备

Java 程序员 后端

2021年去一线大厂面试先过SSM框架源码这一关!,你还看不明白?

Java 程序员 后端

2021年备战金三银四:死磕“源码,百度网盘搜索引擎java

Java 程序员 后端

2021最新华为面经分享:Java高分面试指南(25分类1000题50w字解析

Java 程序员 后端

2020金九银十面试总结,大厂Java面试必会知识点(1),java基础入门第二版第二章答案

Java 程序员 后端

深度学习平台百度飞桨亮相"十三五"科技创新成就展

百度大脑

人工智能 百度

2021年京东、拼多多、腾讯,javaspringboot面试题

Java 程序员 后端

2021全网最新、最全面“互联网大厂面试题库2400页,nginx反向代理负载均衡原理

Java 程序员 后端

2021年九月最新Java面试必背八股文,338道最新大厂架构面试题

Java 程序员 后端

2021备战金三银四血拼一波算法:字节+百度,Java进阶推荐

Java 程序员 后端

2021年Java面试题抢先看,够全!,java技术支持面试题

Java 程序员 后端

更务实的联想,要做钢筋铁骨的边缘智能

脑极体

2020金九银十面试总结,大厂Java面试必会知识点,基础+底层+算法+数据库

Java 程序员 后端

2021-07-22 Java练习题,kafka数据存储原理

Java 程序员 后端

2021最新 SSM(Spring+Spring MVC,java分布式系统面试题

Java 程序员 后端

2021最新Java岗面试清单:15个技术模块(程序员必备,威力加强版

Java 程序员 后端

130道BATJM真题及解析:集合+Spring,华为社招java面试题

Java 程序员 后端

2020年京东Java研发岗社招面经(面试经历+真题总结,java编程教程视频下载

Java 程序员 后端

2021最新美团面经分享:999页Java程序员面试清单(下载量已突破30W

Java 程序员 后端

用四个问题引导员工解决问题

石云升

职场经验 管理经验 10月月更

2021年金三银四最新美团、字节、阿里,阿里巴巴java面试流程

Java 程序员 后端

2020年,阿里最新的java程序员面试题目含答案带你吊打面试官

Java 程序员 后端

【稳定性平台】GOREPLAY流量录制回放实战

得物技术

golang 得物 GOREPLAY 稳定性平台

2021年Java面试题抢先看,够全!中篇,java基础程序

Java 程序员 后端

2021年面试会更难?Java必备209道真题,这份清单助你轻松入阿里

Java 程序员 后端

1年半经验,2本学历,Curd背景,学了阿里P8级架构师的7+1+1落地项目

Java 程序员 后端

2020年IT运维市场大前景到底怎么样,mysql数据库sql语句面试题

Java 程序员 后端

讨论:泛型是否会对性能产生负面影响_.NET_赵劼_InfoQ精选文章