Des*_*ted 35 c# performance where findall
任何人都知道列表中Where和FindAll之间的任何速度差异.我知道IEnumerable的一部分在哪里,FindAll是List的一部分,我只是好奇什么更快.
jri*_*sta 55
List <T>类的FindAll方法实际构造一个新的列表对象,并向其添加结果.IEnumerable <T>的Where扩展方法将简单地迭代现有列表并生成匹配结果的枚举,而无需创建或添加任何内容(枚举器本身除外).
鉴于一小部分,两者可能表现相当.但是,给定一个更大的集合,Where应该优于FindAll,因为为包含结果而创建的新List必须动态增长以包含其他结果.随着匹配结果数量的增加,FindAll的内存使用量也将开始呈指数级增长,其中Where应该具有恒定的最小内存使用量(在其自身内部......排除您对结果所做的任何操作.)
FindAll显然比Where慢,因为它需要创建一个新列表.
无论如何,我认为你真的应该考虑Jon Hanna的评论 - 你可能需要对你的结果做一些操作,在很多情况下列表比IEnumerable更有用.
我写了一个小测试,只需将其粘贴到Console App项目中.它测量时间/滴答:函数执行,结果收集操作(获得'真实'用法的执行,并确保编译器不会优化未使用的数据等 - 我是C#的新手而不是知道它是如何工作的,对不起).
注意:除WhereIENumerable()之外的每个测量函数都会创建新的元素列表.我可能做错了什么,但显然迭代IEnumerable比迭代列表需要更多的时间.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Tests
{
public class Dummy
{
public int Val;
public Dummy(int val)
{
Val = val;
}
}
public class WhereOrFindAll
{
const int ElCount = 20000000;
const int FilterVal =1000;
const int MaxVal = 2000;
const bool CheckSum = true; // Checks sum of elements in list of resutls
static List<Dummy> list = new List<Dummy>();
public delegate void FuncToTest();
public static long TestTicks(FuncToTest function, string msg)
{
Stopwatch watch = new Stopwatch();
watch.Start();
function();
watch.Stop();
Console.Write("\r\n"+msg + "\t ticks: " + (watch.ElapsedTicks));
return watch.ElapsedTicks;
}
static void Check(List<Dummy> list)
{
if (!CheckSum) return;
Stopwatch watch = new Stopwatch();
watch.Start();
long res=0;
int count = list.Count;
for (int i = 0; i < count; i++) res += list[i].Val;
for (int i = 0; i < count; i++) res -= (long)(list[i].Val * 0.3);
watch.Stop();
Console.Write("\r\n\nCheck sum: " + res.ToString() + "\t iteration ticks: " + watch.ElapsedTicks);
}
static void Check(IEnumerable<Dummy> ieNumerable)
{
if (!CheckSum) return;
Stopwatch watch = new Stopwatch();
watch.Start();
IEnumerator<Dummy> ieNumerator = ieNumerable.GetEnumerator();
long res = 0;
while (ieNumerator.MoveNext()) res += ieNumerator.Current.Val;
ieNumerator=ieNumerable.GetEnumerator();
while (ieNumerator.MoveNext()) res -= (long)(ieNumerator.Current.Val * 0.3);
watch.Stop();
Console.Write("\r\n\nCheck sum: " + res.ToString() + "\t iteration ticks :" + watch.ElapsedTicks);
}
static void Generate()
{
if (list.Count > 0)
return;
var rand = new Random();
for (int i = 0; i < ElCount; i++)
list.Add(new Dummy(rand.Next(MaxVal)));
}
static void For()
{
List<Dummy> resList = new List<Dummy>();
int count = list.Count;
for (int i = 0; i < count; i++)
{
if (list[i].Val < FilterVal)
resList.Add(list[i]);
}
Check(resList);
}
static void Foreach()
{
List<Dummy> resList = new List<Dummy>();
int count = list.Count;
foreach (Dummy dummy in list)
{
if (dummy.Val < FilterVal)
resList.Add(dummy);
}
Check(resList);
}
static void WhereToList()
{
List<Dummy> resList = list.Where(x => x.Val < FilterVal).ToList<Dummy>();
Check(resList);
}
static void WhereIEnumerable()
{
Stopwatch watch = new Stopwatch();
IEnumerable<Dummy> iEnumerable = list.Where(x => x.Val < FilterVal);
Check(iEnumerable);
}
static void FindAll()
{
List<Dummy> resList = list.FindAll(x => x.Val < FilterVal);
Check(resList);
}
public static void Run()
{
Generate();
long[] ticks = { 0, 0, 0, 0, 0 };
for (int i = 0; i < 10; i++)
{
ticks[0] += TestTicks(For, "For \t\t");
ticks[1] += TestTicks(Foreach, "Foreach \t");
ticks[2] += TestTicks(WhereToList, "Where to list \t");
ticks[3] += TestTicks(WhereIEnumerable, "Where Ienum \t");
ticks[4] += TestTicks(FindAll, "FindAll \t");
Console.Write("\r\n---------------");
}
for (int i = 0; i < 5; i++)
Console.Write("\r\n"+ticks[i].ToString());
}
}
class Program
{
static void Main(string[] args)
{
WhereOrFindAll.Run();
Console.Read();
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果(滴答) - 启用CheckSum(对结果执行某些操作),模式:不调试释放(CTRL + F5):
CheckSum已禁用(根本不使用返回的列表):
您的结果可能略有不同,要获得真正的结果,您需要更多的迭代.
归档时间: |
|
查看次数: |
20349 次 |
最近记录: |