包含,存在和任何性能的基准testing
我一直在寻找Contains
, Exists
和List<T>
可用的Any
方法之间的性能基准。 我只是出于好奇才发现这一点,因为我一直对此感到困惑。 关于这些方法的许多问题描述了这些方法的定义,如:
- LINQ环:任何()与包含()巨大的集合
- Linq。任何VS.Exists – 有什么区别?
- LINQ扩展方法 – Any()与Where()与Exists()
所以我决定自己做。 我将其添加为答案。 对结果有更多的了解是最受欢迎的。 我也做了这个基准arrays来看结果
据文件记载:
List.Exists(对象方法)
确定List(T)是否包含与由指定谓词定义的条件相匹配的元素。
IEnumerable.Any(扩展方法)
确定序列的任何元素是否满足条件。
List.Contains(对象方法)
确定元素是否在列表中。
标杆:
码:
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); }
结果
*************************************** ***** 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
最快的方法是使用HashSet
。 Contains
一个HashSet
是O(1)。
我把你的代码,并添加了HashSet<int>
的基准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); }
结果
*************************************** ***** 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