首页 > 代码库 > 读书笔记-C#中装箱拆箱性能
读书笔记-C#中装箱拆箱性能
前言
最近在看王涛大神的《你必须知道的.NET(第二版)》一书,嗯,首先膜拜一下….
在书中的第五章-品味类型中,对装箱与拆箱一节感触很深,概念本身相信每一个程序猿都不陌生,装箱是将值类型转换为引用类型 ,拆箱是将引用类型转换为值类型(ps:不小心又背了一下书),也知道装箱与拆箱过程中将带来性能上的问题,但是在实际的项目中往往会忽略这个问题,将可能带来极大的效率上的问题。问题有多大,反正我哭过。
简单对比测试
在工作之余写了个简单的测试例子,以HashTable、ArraryList、List<T>进行了简单的对比。
运行环境:Windows7_64(Cpu:i5; Ram:6GB)。
代码如下:
using System;using System.Collections;using System.Collections.Generic;using System.Diagnostics;namespace Test{ /// <summary> /// 装箱拆箱(HashTable ArraryList List<T>)对比 /// </summary> class Program { static void Main(string[] args) { while (true) { Console.WriteLine("循环次数:"); string strcCycleNum = Console.ReadLine(); int cycleNum = 0; if (!int.TryParse(strcCycleNum, out cycleNum)) { Console.WriteLine("无效输入!"); continue; } HashTableCost(cycleNum); ArraryListCost(cycleNum); GenericCost(cycleNum); } } /// <summary> /// HashTable 开销测试 /// </summary> /// <param name="cycleNum">循环次数</param> static void HashTableCost(int cycleNum) { Stopwatch sw = new Stopwatch(); Hashtable hs_Test = new Hashtable(); sw.Start(); for (int i = 0; i < cycleNum; i++) { hs_Test.Add(i, i); } sw.Stop(); ConsoleInfo(cycleNum, "HashTableCost", sw.ElapsedMilliseconds); } /// <summary> /// ArraryList 开销测试 /// </summary> /// <param name="cycleNum">循环次数</param> static void ArraryListCost(int cycleNum) { Stopwatch sw = new Stopwatch(); ArrayList al_Test = new ArrayList(); sw.Start(); for (int i = 0; i < cycleNum; i++) { al_Test.Add(i); } sw.Stop(); ConsoleInfo(cycleNum, "ArraryListCost", sw.ElapsedMilliseconds); } /// <summary> /// 泛型 开销测试 /// </summary> /// <param name="cycleNum">循环次数</param> static void GenericCost(int cycleNum) { Stopwatch sw = new Stopwatch(); List<int> lTest = new List<int>(); sw.Start(); for (int i = 0; i < cycleNum; i++) { lTest.Add(i); } sw.Stop(); ConsoleInfo(cycleNum, "GenericCost", sw.ElapsedMilliseconds); } /// <summary> /// 打印信息 /// </summary> /// <param name="cycleNum">循环次数</param> /// <param name="methodName">方法名称</param> /// <param name="cost">开销</param> static void ConsoleInfo(int cycleNum, string methodName, long cost) { Console.WriteLine(methodName + " 循环次数:" + cycleNum.ToString() + " 开销(毫秒):" + cost.ToString()); } }}测试结果:
对于测试结果还是很惊讶,循环添加1000次,3者都为0毫秒,在10W与100W次的结果出现了鲜明的对比分别为305ms,86ms,9ms。差距不是一般的大。
对代码进行分析:
// HashTable : public virtual void Add(object key, object value); // 在Add的过程中进行了2次装箱 hs_Test.Add(i, i);
HashTable.add()都会产生2次装箱。
// public virtual int Add(object value);// 产生了一次装箱 al_Test.Add(i);ArraryList.add产生2次装箱。
// 由于lTest 指定了类型(List<int>)并没有产生装箱lTest.Add(i);
List<int>没有产生装箱。
也可以通过IL对代码进行分析,这里就不再列出了。
总结
在对大量数据进行操作的时候一定要注意装箱与拆箱操作,可以用泛型代替的地方还是使用泛型吧。
在平时的一般项目中的细节也需要注意,毕竟细节决定成败,再NB的框架,也经不起这一片片的装箱与拆箱的轰炸。
(ps:隐式转换的时候要细心,在转换成字符串的时候习惯使用ToString(),毕竟是不产生装箱的。)
读书笔记-C#中装箱拆箱性能
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。