C# 包含、存在和任何的性能基准测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18651940/
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
Performance Benchmarking of Contains, Exists and Any
提问by harshit
I have been searching for a performance benchmarking between Contains
, Exists
and Any
methods available in the List<T>
. I wanted to find this out just out of curiosity as I was always confused among these. Many questions on SO described definitions of these methods such as:
我一直在寻找一个业绩之间标杆Contains
,Exists
和Any
方法可用List<T>
。我只是出于好奇而想找出这一点,因为我总是对这些感到困惑。关于 SO 的许多问题描述了这些方法的定义,例如:
- LINQ Ring: Any() vs Contains() for Huge Collections
- Linq .Any VS .Exists - Whats the difference?
- LINQ extension methods - Any() vs. Where() vs. Exists()
- LINQ Ring:Any() 与 Contains() 用于巨大的集合
- Linq .Any VS .Exists - 有什么区别?
- LINQ 扩展方法 - Any() vs. Where() vs. Exists()
So I decided to do it myself. I am adding it as an answer. Any more insight on the results is most welcomed. I also did this benchmarking for arrays to see the results
所以我决定自己做。我将其添加为答案。任何对结果的更多见解都是最受欢迎的。我还对数组进行了此基准测试以查看结果
采纳答案by harshit
According to documentation:
根据文档:
List.Exists (Object method)
List.Exists(对象方法)
Determines whether the List(T) contains elements that match the conditions defined by the specified predicate.
确定 List(T) 是否包含与指定谓词定义的条件匹配的元素。
IEnumerable.Any (Extension method)
IEnumerable.Any(扩展方法)
Determines whether any element of a sequence satisfies a condition.
确定序列的任何元素是否满足条件。
List.Contains (Object Method)
List.Contains(对象方法)
Determines whether an element is in the List.
确定元素是否在 List 中。
Benchmarking:
基准测试:
CODE:
代码:
static void Main(string[] args)
{
ContainsExistsAnyShort();
ContainsExistsAny();
}
private static void ContainsExistsAny()
{
Console.WriteLine("***************************************");
Console.WriteLine("********* ContainsExistsAny ***********");
Console.WriteLine("***************************************");
List<int> list = new List<int>(6000000);
Random random = new Random();
for (int i = 0; i < 6000000; i++)
{
list.Add(random.Next(6000000));
}
int[] arr = list.ToArray();
find(list, arr);
}
private static void ContainsExistsAnyShort()
{
Console.WriteLine("***************************************");
Console.WriteLine("***** ContainsExistsAnyShortRange *****");
Console.WriteLine("***************************************");
List<int> list = new List<int>(2000);
Random random = new Random();
for (int i = 0; i < 2000; i++)
{
list.Add(random.Next(6000000));
}
int[] arr = list.ToArray();
find(list, arr);
}
private static void find(List<int> list, int[] arr)
{
Random random = new Random();
int[] find = new int[10000];
for (int i = 0; i < 10000; i++)
{
find[i] = random.Next(6000000);
}
Stopwatch watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
list.Contains(find[rpt]);
}
watch.Stop();
Console.WriteLine("List/Contains: {0:N0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
list.Exists(a => a == find[rpt]);
}
watch.Stop();
Console.WriteLine("List/Exists: {0:N0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
list.Any(a => a == find[rpt]);
}
watch.Stop();
Console.WriteLine("List/Any: {0:N0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
arr.Contains(find[rpt]);
}
watch.Stop();
Console.WriteLine("Array/Contains: {0:N0}ms", watch.ElapsedMilliseconds);
Console.WriteLine("Arrays do not have Exists");
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
arr.Any(a => a == find[rpt]);
}
watch.Stop();
Console.WriteLine("Array/Any: {0:N0}ms", watch.ElapsedMilliseconds);
}
RESULTS
结果
***************************************
***** ContainsExistsAnyShortRange *****
***************************************
List/Contains: 96ms
List/Exists: 146ms
List/Any: 381ms
Array/Contains: 34ms
Arrays do not have Exists
Array/Any: 410ms
***************************************
********* ContainsExistsAny ***********
***************************************
List/Contains: 257,996ms
List/Exists: 379,951ms
List/Any: 884,853ms
Array/Contains: 72,486ms
Arrays do not have Exists
Array/Any: 1,013,303ms
回答by wertzui
The fastest way is to use a HashSet
.
The Contains
for a HashSet
is O(1).
最快的方法是使用HashSet
. 的Contains
一个HashSet
是O(1)。
I took you code and added a benchmark for HashSet<int>
The performance cost of HashSet<int> set = new HashSet<int>(list);
is nearly zero.
我带你代码并添加了一个基准测试HashSet<int>
性能成本HashSet<int> set = new HashSet<int>(list);
几乎为零。
void Main()
{
ContainsExistsAnyShort();
ContainsExistsAny();
}
private static void ContainsExistsAny()
{
Console.WriteLine("***************************************");
Console.WriteLine("********* ContainsExistsAny ***********");
Console.WriteLine("***************************************");
List<int> list = new List<int>(6000000);
Random random = new Random();
for (int i = 0; i < 6000000; i++)
{
list.Add(random.Next(6000000));
}
int[] arr = list.ToArray();
HashSet<int> set = new HashSet<int>(list);
find(list, arr, set);
}
private static void ContainsExistsAnyShort()
{
Console.WriteLine("***************************************");
Console.WriteLine("***** ContainsExistsAnyShortRange *****");
Console.WriteLine("***************************************");
List<int> list = new List<int>(2000);
Random random = new Random();
for (int i = 0; i < 2000; i++)
{
list.Add(random.Next(6000000));
}
int[] arr = list.ToArray();
HashSet<int> set = new HashSet<int>(list);
find(list, arr, set);
}
private static void find(List<int> list, int[] arr, HashSet<int> set)
{
Random random = new Random();
int[] find = new int[10000];
for (int i = 0; i < 10000; i++)
{
find[i] = random.Next(6000000);
}
Stopwatch watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
list.Contains(find[rpt]);
}
watch.Stop();
Console.WriteLine("List/Contains: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
list.Exists(a => a == find[rpt]);
}
watch.Stop();
Console.WriteLine("List/Exists: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
list.Any(a => a == find[rpt]);
}
watch.Stop();
Console.WriteLine("List/Any: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
arr.Contains(find[rpt]);
}
watch.Stop();
Console.WriteLine("Array/Contains: {0}ms", watch.ElapsedMilliseconds);
Console.WriteLine("Arrays do not have Exists");
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
arr.Any(a => a == find[rpt]);
}
watch.Stop();
Console.WriteLine("Array/Any: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 10000; rpt++)
{
set.Contains(find[rpt]);
}
watch.Stop();
Console.WriteLine("HashSet/Contains: {0}ms", watch.ElapsedMilliseconds);
}
RESULTS
结果
***************************************
***** ContainsExistsAnyShortRange *****
***************************************
List/Contains: 65ms
List/Exists: 106ms
List/Any: 222ms
Array/Contains: 20ms
Arrays do not have Exists
Array/Any: 281ms
HashSet/Contains: 0ms
***************************************
********* ContainsExistsAny ***********
***************************************
List/Contains: 120522ms
List/Exists: 250445ms
List/Any: 653530ms
Array/Contains: 40801ms
Arrays do not have Exists
Array/Any: 522371ms
HashSet/Contains: 3ms
回答by LuckyBrain
It is worth mentioning that this comparison is a bit unfair since the Array
class doesn't own the Contains()
method, it uses an extension method for IEnumerable<T>
via a sequential Enumerator
hence it is not optimized for Array
instances; on the other side, HashSet<T>
has its own implementation fully optimized for all sizes.
值得一提的是,这种比较有点不公平,因为Array
该类不拥有该Contains()
方法,它使用了一个扩展方法 for IEnumerable<T>
via 顺序Enumerator
因此它没有针对Array
实例进行优化;另一方面,HashSet<T>
它有自己的实现,完全针对所有尺寸进行了优化。
To compare fairly you could use the static method int Array.IndexOf()
which is implemented for Array
instances even though it uses a for
loop slightly more efficient that an Enumerator
.
为了公平比较,您可以使用int Array.IndexOf()
为Array
实例实现的静态方法,即使它使用的for
循环比Enumerator
.
Having said that, the performance of HashSet<T>.Contains()
is similar to the Array.IndexOf()
for small sets of, I would say, up to 5 elements and much more efficient for large sets.
话虽如此, 的性能HashSet<T>.Contains()
类似于Array.IndexOf()
小集合,我想说,最多 5 个元素,并且对于大集合效率更高。