• [技术相关]List、Dictionary转Dictionary的性能分析


    1.    背景

      我们经常有对List和Dictionary列表进行复制、转换等操作,在数据量较少时(几万以内)各种转换速度不会被觉察,但是数据量很大时(百万左右),各种转换方式的性能就会体现出来。

      本文档将对列表转换效率进行测试,最终得出效率较高的方法,指导今后软件开发对技术的选择。另外,本文还将对列表转换过程中由另一线程修改列表数据时,是否会出现异常进行确认。

      2013年5月16日星期四

    2.    结论

      1、在Dictionary转Dictionary过程中由另一线程修改列表数据时,会出现异常。

      2、采用Dictionary.ToDictionary()的方式速度很慢,100万条需要249毫秒

      3、采用Dictionary.Value.ToList的方式速度很快,100万条数据仅32毫秒;

      4、List.ToDictionary的方式速度需要109毫秒;

    3.    环境

      1)开发环境采用VS2008,C#程序,手动编写代码实现。

      2)测试列表中包含100万条数据。

    4.    分析

    4.1.  过程1:修改列表,是否对转换造成异常

      1、方法:用两个线程,一个线程负责Dictionary转换,一个对列表进行修改。

          结果:系统报错,确实会出现异常。

      2、详细说明(详情参见下方源代码)

         用线程函数TH_DicTest0()进行转换操作,用线程函数TH_DicTest1()进行列表内容修改操作。

    4.2.  过程2:列表转换速度分析

      1、方法1:采用Dictionary.ToDictionary()的方式,

        结果:16:44:08 标识:[ToDic时间] 运行时间为:249; 运行次数:1

      2、方法2:采用Dictionary.Value.ToList,然后再List.ToDictionary的方式进行转换;

        结果:

        1)Dictionary.Value.ToList的方式用时:

          16:44:08 标识:[ToList时间] 运行时间为:32; 运行次数:1

        2)List.ToDictionary的方式用时:

          16:44:08 标识:[转Dic时间] 运行时间为:109; 运行次数:1

     1         #region Dictionary测试
     2         private MainThread _tt0 = new MainThread();
     3         private MainThread _tt1 = new MainThread();
     4         private Dictionary<int, DataTestItem> _dicTest = new Dictionary<int, DataTestItem>();
     5         private Dictionary<int, DataTestItem> _dicTest1;
     6         private void button17_Click(object sender, EventArgs e)
     7         {
     8             Init_DicTest();
     9 
    10             _tt0.Add(TH_DicTest0, 1);
    11             _tt1.Add(TH_DicTest1, 1);
    12 
    13             //_tt1.Start();
    14             _tt0.Start();
    15         }
    16         private void Init_DicTest()
    17         {
    18             DataTestItem item = null;
    19             for (int i = 0; i < 1000000; i++ )
    20             {
    21                 item = new DataTestItem();
    22                 item.a1 = i;
    23                 item.a2 = i + 1;
    24                 _dicTest.Add(item.a1, item);
    25             }
    26         }
    27         private List<DataTestItem> _lstTest = null;
    28         private void TH_DicTest0()
    29         {
    30             try
    31             {
    32                 RunTimeScan.Instance().Begin("ToList时间");
    33                 _dicTest1 = new Dictionary<int, DataTestItem>();
    34                 _lstTest = _dicTest.Values.ToList();
    35                 RunTimeScan.Instance().Stop("ToList时间");
    36 
    37                 RunTimeScan.Instance().Begin("转Dic时间");
    38                 foreach (DataTestItem item in _lstTest)
    39                 {
    40                     _dicTest1.Add(item.a1, item);
    41                 }
    42                 RunTimeScan.Instance().Stop("转Dic时间");
    43 
    44                 RunTimeScan.Instance().Begin("ToDic时间");
    45                 _dicTest1 = _dicTest.ToDictionary(p => p.Key, p => p.Value);
    46                 RunTimeScan.Instance().Stop("ToDic时间");
    47 
    48                 AddTipMsg(RunTimeScan.Instance().GetRet("ToList时间"));
    49                 AddTipMsg(RunTimeScan.Instance().GetRet("转Dic时间"));
    50                 AddTipMsg(RunTimeScan.Instance().GetRet("ToDic时间"));
    51             }
    52             catch (System.Exception ex)
    53             {
    54                 AddTipMsg(ex.Message + ex.StackTrace);
    55             }
    56         }
    57         private void TH_DicTest1()
    58         {
    59             try
    60             {
    61                 RunTimeScan.Instance().Begin("Add_100");
    62 
    63                 DataTestItem item = null;
    64                 for (int i = 0; i < 100; i++)
    65                 {
    66                     item = new DataTestItem();
    67                     item.a1 = _dicTest.Count() + i;
    68                     item.a2 = i + 1;
    69                     _dicTest.Add(item.a1, item);
    70                     Thread.Sleep(20);
    71                 }
    72 
    73                 RunTimeScan.Instance().Stop("Add_100");
    74                 AddTipMsg(RunTimeScan.Instance().GetRet("Add_100"));
    75             }
    76             catch (System.Exception ex)
    77             {
    78                 AddTipMsg(ex.Message + ex.StackTrace);
    79             }
    80         }
    81         #endregion
    View Code
  • 相关阅读:
    游戏与必胜策略
    中国剩余定理
    中国剩余定理
    欧几里得和扩展欧几里得
    欧几里得和扩展欧几里得
    51nod 1028 大数乘法 V2
    51nod 1028 大数乘法 V2
    51nod 1029 大数除法
    51nod 1029 大数除法
    51nod 1166 大数开平方
  • 原文地址:https://www.cnblogs.com/easydw/p/3509238.html
Copyright © 2020-2023  润新知