C# FindAll VS Where 速度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2260220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# FindAll VS Where Speed
提问by Dested
Anyone know any speed differences between Where and FindAll on List. I know Where is part of IEnumerable and FindAll is part of List, I'm just curious what's faster.
任何人都知道 Where 和 FindAll on List 之间的速度差异。我知道 Where 是 IEnumerable 的一部分,FindAll 是 List 的一部分,我只是好奇什么更快。
采纳答案by jrista
The FindAll method of the List<T> class actually constructs a new list object, and adds results to it. The Where extension method for IEnumerable<T> will simply iterate over an existing list and yield an enumeration of the matching results without creating or adding anything (other than the enumerator itself.)
List<T> 类的 FindAll 方法实际上构造了一个新的列表对象,并将结果添加到其中。IEnumerable<T> 的 Where 扩展方法将简单地遍历现有列表并生成匹配结果的枚举,而无需创建或添加任何内容(枚举器本身除外)。
Given a small set, the two would likely perform comparably. However, given a larger set, Where should outperform FindAll, as the new List created to contain the results will have to dynamically grow to contain additional results. Memory usage of FindAll will also start to grow exponentially as the number of matching results increases, where as Where should have constant minimal memory usage (in and of itself...excluding whatever you do with the results.)
给定一小部分,两者的表现可能相当。然而,给定一个更大的集合,Where 应该优于 FindAll,因为为包含结果而创建的新列表将必须动态增长以包含其他结果。FindAll 的内存使用量也将随着匹配结果数量的增加而开始呈指数增长,其中 Where 应该具有恒定的最小内存使用量(就其本身而言......排除您对结果所做的任何事情。)
回答by Nick Craver
.FindAll()
should be faster, it takes advantage of already knowing the List's size and looping through the internal array with a simple for
loop. .Where()
has to fire up an enumerator (a sealed framework class called WhereIterator
in this case) and do the same job in a less specific way.
.FindAll()
应该更快,它利用已经知道 List 的大小并使用简单for
循环遍历内部数组的优势。 .Where()
必须启动一个枚举器(WhereIterator
在这种情况下称为密封框架类)并以不太具体的方式完成相同的工作。
Keep in mind though, that .Where() is enumerable, not actively creating a List in memory and filling it. It's more like a stream, so the memory use on something very large can have a significant difference. Also, you could start using the results in a parallel fashion much faster using there .Where() approach in 4.0.
但请记住, .Where() 是可枚举的,而不是主动在内存中创建 List 并填充它。它更像是一个流,因此在非常大的东西上的内存使用可能会有显着差异。此外,您可以在 4.0 中使用 there.Where() 方法以更快的速度开始以并行方式使用结果。
回答by Jonathan Allen
Where
is much, much faster than FindAll
. No matter how big the list is, Where
takes exactly the same amount of time.
Where
比 快得多FindAll
。无论列表有多大,Where
花费的时间都完全相同。
Of course Where
just creates a query. It doesn't actually do anything, unlike FindAll
which does create a list.
当然Where
只是创建一个查询。它实际上没有做任何事情,与FindAll
创建列表不同。
回答by Eric
The answer from jrista makes senses. However, the new list adds the same objects, thus just growing with reference to existing objects, which should not be that slow. As long as 3.5 / Linq extension are possible, Where stays better anyway. FindAll makes much more sense when limited with 2.0
jrista 的回答是有道理的。但是,新列表添加了相同的对象,因此只是参考现有对象而增长,这应该不会那么慢。只要 3.5 / Linq 扩展是可能的,不管怎样,哪里会更好。FindAll 在受 2.0 限制时更有意义
回答by Wiory
FindAll is obviously slower than Where, because it needs to create a new list.
FindAll 显然比 Where 慢,因为它需要创建一个新列表。
Anyway, I think you really should consider Jon Hanna comment - you'll probably need to do some operations on your results and list would be more useful than IEnumerable in many cases.
无论如何,我认为您真的应该考虑 Jon Hanna 的评论-您可能需要对结果进行一些操作,并且在许多情况下,列表比 IEnumerable 更有用。
I wrote small test, just paste it in Console App project. It measures time/ticks of: function execution, operations on results collection(to get perf. of 'real' usage, and to be sure that compiler won't optimize unused data etc. - I'm new to C# and don't know how it works yet,sorry).
我写了一个小测试,只需将其粘贴到 Console App 项目中即可。它测量以下时间/滴答:函数执行、结果收集操作(以获得“真实”使用的性能,并确保编译器不会优化未使用的数据等。我是 C# 的新手,不会知道它是如何工作的,抱歉)。
Notice: every measured function except WhereIENumerable() creates new List of elements. I might be doing something wrong, but clearly iterating IEnumerable takes much more time than iterating list.
注意:除了 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();
}
}
}
Results(ticks)- CheckSum enabled(some operations on results), mode: release without debugging(CTRL+F5):
结果(滴答声)- CheckSum 启用(对结果进行一些操作),模式:发布而不调试(CTRL+F5):
- 16222276 (for ->list)
- 17151121 (foreach -> list)
- 4741494 (where ->list)
- 27122285 (where ->ienum)
- 18821571 (findall ->list)
- 16222276(用于 -> 列表)
- 17151121(foreach -> 列表)
- 4741494(其中 -> 列表)
- 27122285(其中 ->ienum)
- 18821571(查找所有 -> 列表)
CheckSum disabled (not using returned list at all):
CheckSum 已禁用(根本不使用返回的列表):
- 10885004 (for ->list)
- 11221888 (foreach ->list)
- 18688433 (where ->list)
- 1075 (where ->ienum)
- 13720243 (findall ->list)
- 10885004(用于 -> 列表)
- 11221888(foreach -> 列表)
- 18688433(其中 -> 列表)
- 1075(其中 -> ienum)
- 13720243(查找全部 -> 列表)
Your results can be slightly different, to get real results you need more iterations.
您的结果可能略有不同,要获得真正的结果,您需要更多的迭代。