泛型真的会降低性能吗?

  在《.NET,你忘记了么?(八)—— 从dynamic到特性误用》一文中,飞林沙同学提到,使用泛型会略微降低程序性能,因此在程序中使用List是不合理的行为,应该使用ArrayList。这一点和老赵平时的观点相悖,老赵一直提倡,在.NET 2.0之后,要尽可能使用List,情愿是List也不要使用ArrayList。不过个中原因与性能无关,我们稍候再叙述。飞同学的文章让我有了将泛型与非泛型进行性能比较的想法。这个比较非常容易,不过也得出了一些非常有意思的结论。 泛型容器与非泛型容器的性能比较  首先,我们来比较一种最“纯粹”的泛型容器,它的目的是避免程序的其他方面对性能的影响。因此,这里我们构造两个最简单的容器,就是简单的模仿ArrayList和List: public class MyArrayList { public MyArrayList(int length) { this.m_items = new object[length]; } public object[] m_items; public object this[int index] { get { return this.m_items[index]; } set { this.m_items[index] = value; } } public IEnumerable InnerContainer { get { return this.m_items; } } } public class MyList { public MyList(int length) { this.m_items = new T[length]; } public T[] m_items; public T this[int index] { get { return this.m_items[index]; } set { this.m_items[index] = value; } } public IEnumerable InnerContainer { get { return this.m_items; } } }   MyArrayList为直接使用Object类型的容器,而MyList则是泛型容器。老赵为他们实现了两种操作,一是下标访问,二是直接把内部的数组容器作为可遍历的对象释放出来。这两种都是平时编程中最经常使用的操作。   于是我们就可以编写测试代码了。首先,我们初始化两种容器,并进行“预热”: int length = 1000; object value = new object(); MyArrayList myArrayList = new MyArrayList(length); for (int i = 0; i < length; i++) { myArrayList[i] = myArrayList[i] ?? value; } MyListmyList = new MyList(length); for (int i = 0; i < length; i++) { myList[i] = myList[i] ?? value; }   然后我们使用CodeTimer来进行统计: CodeTimer.Initialize(); int iteration = 300 * 1000; CodeTimer.Time("MyArrayList下标访问", iteration, () => { for (int i = 0; i < length; i++) { var o = myArrayList[i]; } }); CodeTimer.Time("MyList下标访问", iteration, () => { for (int i = 0; i < length; i++) { var o = myList[i]; } });   Release Build并运行。猜猜看,结果是什么? MyArrayList下标访问 Time Elapsed: 2,398ms CPU Cycles: 5,042,561,997 Gen 0: 0 Gen 1: 0 Gen 2: 0 MyList下标访问 Time Elapsed: 2,285ms CPU Cycles: 4,935,066,741 Gen 0: 0 Gen 1: 0 Gen 2: 0  以上是在老赵的机器上得到的结果,从结果上看,泛型的MyList性能甚至略比MyArrayList有所提高。当然测试的结果其实是互有胜负,但是事实上,MyList的获胜的次数甚至还略有领先。   那么我们再来看看“遍历”的性能如何: CodeTimer.Time("MyArrayList遍历", iteration, () => { foreach (object o in myArrayList.InnerContainer) { var o1 = o; } }); CodeTimer.Time("MyList遍历", iteration, () => { foreach (object o in myList.InnerContainer) { var o1 = o; } });   运行的结果颇有意思: MyArrayList遍历 Time Elapsed: 21,367ms CPU Cycles: 46,023,627,496 Gen 0: 2 Gen 1: 1 Gen 2: 0 MyList遍历 Time Elapsed: 3,463ms CPU Cycles: 7,448,928,223 Gen 0: 2 Gen 1: 0 Gen 2: 0  直接使用Object的MyArrayList性能居然差了这么多!个中原因老赵有所猜测,在得到明确答案之后会接着与大家分享。 ArrayList和List的性能  刚才比较了最“纯粹”的性能,那么我们再来比较ArrayList和List。因为我们其实不知道它俩具体在实现上的细节是如何的,还是比较一下这两个容器具体的性能比较好。比较的内容还是两项:下标访问及遍历。代码如下: int length = 1000; object value = new object(); ArrayList arrayList = new ArrayList(length); for (int i = 0; i < length; i++) { arrayList.Add(value); arrayList[i] = arrayList[i] ?? value; } Listlist = new List(length); for (int i = 0; i < length; i++) { list.Add(value); list[i] = list[i] ?? value; } CodeTimer.Initialize(); int iteration = 300 * 1000; CodeTimer.Time("ArrayList下标访问", iteration, () => { for (int i = 0; i < length; i++) { var o = arrayList[i]; } }); CodeTimer.Time("List下标访问", iteration, () => { for (int i = 0; i < length; i++) { var o = list[i]; } }); CodeTimer.Time("ArrayList遍历", iteration, () => { foreach (object o in arrayList) { var o1 = o; } }); CodeTimer.Time("List遍历", iteration, () => { foreach (object o in list) { var o1 = o; } });   结果如下: ArrayList下标访问 Time Elapsed: 2,282ms CPU Cycles: 4,838,476,797 Gen 0: 0 Gen 1: 0 Gen 2: 0 List下标访问 Time Elapsed: 2,302ms CPU Cycles: 4,979,267,920 Gen 0: 0 Gen 1: 0 Gen 2: 0 ArrayList遍历 Time Elapsed: 5,187ms CPU Cycles: 11,145,830,014 Gen 0: 4 Gen 1: 0 Gen 2: 0 List遍历 Time Elapsed: 2,989ms CPU Cycles: 6,459,825,955 Gen 0: 0 Gen 1: 0 Gen 2: 0  现在您还觉得泛型会降低性能,List比ArrayList的性能差吗? 总结  从结果上已经可以看出,泛型并不会影响性能,而List的性能也不比ArrayList要差。因此老赵继续坚持:在有泛型支持的情况下,尽量使用泛型容器。例如使用List而不是ArrayList。除了“性能”之外,老赵的还有其他一些理由。例如使用List的话就可以使用框架内部所定义的各种有用的辅助方法(要知道在.NET框架中,现在几乎都是在针对IEnumerable进行开发);而我们平时写程序时,也可以统一的针对泛型编程,如IList,IEnumerable,不必考虑List或Enumerable等非泛型元素。   放心使用List吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值