项目经验总结(三)哪种方式查询泛型集合性能上最佳

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

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

代码
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效果更佳。

 

posted on 2010-11-04 09:42  min.jiang  阅读(3502)  评论(17编辑  收藏  举报