zoukankan      html  css  js  c++  java
  • 项目经验总结(三)哪种方式查询泛型集合性能上最佳

        这篇文章我来分析下对于泛型集合,采取不同的查询方式在性能上会有什么样的影响?

        这里有一个城市简单信息的实体类:
        

    代码
    class CityInfo
        {
            
    public int CityID
            {
                
    get;
                
    set;
            }
            
    public string CityName
            {
                
    get;
                
    set;
            }
            
    public string CityNameEn
            {
                
    get;
                
    set;
            }
            
    public string CityAddress 
            { 
                
    get
                
    set;
            }
        }

         我们构造一个特别大的城市泛型类:
         

    代码
                int i = 100000;
                Random m 
    = new Random();
                List
    <CityInfo> list = new List<CityInfo>();
                
    for (int j = 0; j < i; j++)
                {
                    CityInfo info 
    = new CityInfo();
                    info.CityID 
    = j;
                    info.CityAddress 
    = "aaaaaa" + j.ToString();
                    info.CityName 
    = "城市中文名称" + j.ToString();
                    info.CityNameEn 
    = "城市英文名称" + j.ToString();
                    list.Add(info);
                }

         根据城市ID查询某个城市的具体信息:
         方法一:foreach:
           

    代码
            static CityInfo GetCityInfoByForeach(List<CityInfo> list, int CityID)
            {
                CityInfo info 
    = new CityInfo();
                
    foreach (var item in list)
                {
                    
    if (item.CityID == CityID)
                    {
                        info 
    = item;
                        breake;
                    }
                }
                
    return info;
            }

          方法二:for循环:
          

    代码
            static CityInfo GetCityInfoByFor(List<CityInfo> list, int CityID)
            {
                CityInfo info 
    = new CityInfo();
                
    for (int i = 0; i < list.Count;i ++ )
                {
                    
    if (list[i].CityID == CityID)
                    {
                        info 
    = list [i];
                        breake;

                     }
                }
                
    return info;
            }

         方法三:Linq查询:
         

    代码
            static CityInfo GetCityInfoByLinq(List<CityInfo> list,int CityID)
            {
                CityInfo info 
    = new CityInfo();
                info 
    = list.Where(p => p.CityID == CityID).FirstOrDefault();
                
    return info;
            }

          然后随机产生一个城市ID,分别针对上面三种方式调用500次,这里何用老赵的CodeTimer来显示信息,执行结果如下:

         

    代码
           CodeTimer.Time("GetCityInfoByForeach"500, () => GetCityInfoByForeach(list, m.Next(i - 1)));
           CodeTimer.Time(
    "GetCityInfoByFor"500, () => GetCityInfoByFor(list, m.Next(i - 1)));
           CodeTimer.Time(
    "GetCityInfoByLinq"500, () => GetCityInfoByLinq(list, m.Next(i - 1)));

         

      

           性能从高到低表现为:for,foreach,linq,仔细查看三种方法生成IL代码,有一定的区别:
           1:foreach方法在查询数据时,依赖了Enumerator ,它的特点是不能像对于数组一样使用索引,而只能将当前项指针移动到集合的第一个或下一个元素,这是它性能不是最优的主要问题所在。在这种方式中还有一个重要点就是在查询每个元素时都会有try finally块,这也是需要消耗部分性能的。
          

    代码
      .try
      {
        IL_000d:  br.s       IL_0022
        IL_000f:  ldloca.s   CS$
    5$0000
        IL_0011:  call       instance 
    !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class ConsoleApplication1.CityInfo>::get_Current()
        IL_0016:  stloc.
    1
        IL_0017:  ldloc.
    1
        IL_0018:  callvirt   instance int32 ConsoleApplication1.CityInfo::get_CityID()
        IL_001d:  ldarg.
    1
        IL_001e:  bne.un.s   IL_0022
        IL_0020:  ldloc.
    1
        IL_0021:  stloc.
    0
        IL_0022:  ldloca.s   CS$
    5$0000
        IL_0024:  call       instance 
    bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class ConsoleApplication1.CityInfo>::MoveNext()
        IL_0029:  brtrue.s   IL_000f
        IL_002b:  leave.s    IL_003b
      }  
    // end .try
      finally
      {
        IL_002d:  ldloca.s   CS$
    5$0000
        IL_002f:  constrained. valuetype [mscorlib]System.Collections.Generic.List`
    1/Enumerator<class ConsoleApplication1.CityInfo>
        IL_0035:  callvirt   instance 
    void [mscorlib]System.IDisposable::Dispose()
        IL_003a:  endfinally
      }  
    // end handler

          2:for方法在查询数据时,System.Collections.Generic.List`1<class ConsoleApplication1.CityInfo>::get_Item(int32),比起foreach少了try的处理,最重要的是能够使用索引访问元素。

          3:linq方式性能最差。

          非常感谢各位朋友的指点,特别是代码中忘记加break,现在是修改代码后的测试结果:结果和上面一样。

         

     

          本篇文章的测试代码

      

          总结:泛型集合如果数据量大,最好采用for循环查询,数据量少的话,用linq方式最佳,代码优雅且简洁。

          题外话:其实针对这种泛型集合查询,如果想优化性能,最好不要存储成泛型集合,采用Dictionary或者是hashtable效果更佳。

  • 相关阅读:
    纸牌游戏----小猫钓鱼
    数据结构-----栈
    浅谈队列
    排序算法实例
    排序算法之------快速排序
    排序算法之----冒泡排序
    Visual Studio-基本使用
    C++-GUID from string
    OS-Windows CMD生成文件夹目录结构
    OS-Windows10 DownLoad
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/1868633.html
Copyright © 2011-2022 走看看