读书笔记-C#中装箱拆箱性能

2020-12-13 15:55

阅读:509

标签:style   blog   http   io   color   ar   os   使用   for   

 

前言

  最近在看王涛大神的《你必须知道的.NET(第二版)》一书,嗯,首先膜拜一下….

  在书中的第五章-品味类型中,对装箱与拆箱一节感触很深,概念本身相信每一个程序猿都不陌生,装箱是将值类型转换为引用类型 ,拆箱是将引用类型转换为值类型(ps:不小心又背了一下书),也知道装箱与拆箱过程中将带来性能上的问题,但是在实际的项目中往往会忽略这个问题,将可能带来极大的效率上的问题。问题有多大,反正我哭过。

简单对比测试

  在工作之余写了个简单的测试例子,以HashTable、ArraryList、List进行了简单的对比。

  运行环境:Windows7_64(Cpu:i5; Ram:6GB)。

  代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace Test
{
    /// 
    /// 装箱拆箱(HashTable ArraryList List)对比
    /// 
    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);
            }
        }

        /// 
        /// HashTable 开销测试
        /// 
        /// 循环次数
        static void HashTableCost(int cycleNum)
        {
            Stopwatch sw = new Stopwatch();
            Hashtable hs_Test = new Hashtable();
            sw.Start();
            for (int i = 0; i )
            {
                hs_Test.Add(i, i);
            }
            sw.Stop();
            ConsoleInfo(cycleNum, "HashTableCost", sw.ElapsedMilliseconds);
        }

        /// 
        /// ArraryList 开销测试
        /// 
        /// 循环次数
        static void ArraryListCost(int cycleNum)
        {
            Stopwatch sw = new Stopwatch();
            ArrayList al_Test = new ArrayList();
            sw.Start();
            for (int i = 0; i )
            {
                al_Test.Add(i);
            }
            sw.Stop();
            ConsoleInfo(cycleNum, "ArraryListCost", sw.ElapsedMilliseconds);
        }

        /// 
        /// 泛型 开销测试
        /// 
        /// 循环次数
        static void GenericCost(int cycleNum)
        {
            Stopwatch sw = new Stopwatch();
            Listint> lTest = new Listint>();
            sw.Start();
            for (int i = 0; i )
            {
                lTest.Add(i);
            }
            sw.Stop();
            ConsoleInfo(cycleNum, "GenericCost", sw.ElapsedMilliseconds);
        }

        /// 
        /// 打印信息
        /// 
        /// 循环次数
        /// 方法名称
        /// 开销
        static void ConsoleInfo(int cycleNum, string methodName, long cost)
        {
            Console.WriteLine(methodName + " 循环次数:" + cycleNum.ToString() + "  开销(毫秒):" + cost.ToString());
        }

    }
}

测试结果:

soscw.com,搜素材

对于测试结果还是很惊讶,循环添加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)并没有产生装箱
lTest.Add(i);

List没有产生装箱。

也可以通过IL对代码进行分析,这里就不再列出了。

总结

在对大量数据进行操作的时候一定要注意装箱与拆箱操作,可以用泛型代替的地方还是使用泛型吧。

在平时的一般项目中的细节也需要注意,毕竟细节决定成败,再NB的框架,也经不起这一片片的装箱与拆箱的轰炸。

(ps:隐式转换的时候要细心,在转换成字符串的时候习惯使用ToString(),毕竟是不产生装箱的。)

读书笔记-C#中装箱拆箱性能

标签:style   blog   http   io   color   ar   os   使用   for   

原文地址:http://www.cnblogs.com/panxmin/p/4077594.html


评论


亲,登录后才可以留言!