Performance Benchmarking of Contains, Exists and Any

后端 未结 3 542
逝去的感伤
逝去的感伤 2020-12-04 08:53

I have been searching for a performance benchmarking between Contains, Exists and Any methods available in the List

相关标签:
3条回答
  • 2020-12-04 09:06

    According to documentation:

    List.Exists (Object method)

    Determines whether the List(T) contains elements that match the conditions defined by the specified predicate.

    IEnumerable.Any (Extension method)

    Determines whether any element of a sequence satisfies a condition.

    List.Contains (Object Method)

    Determines whether an element is in the 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
    
    0 讨论(0)
  • 2020-12-04 09:16

    The fastest way is to use a HashSet. The Contains for a HashSet is 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.

    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
    
    0 讨论(0)
  • 2020-12-04 09:16

    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.

    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.

    Using a fair comparison algorithm, the performance for small sets of up to 5 elements of HashSet<T>.Contains() is similar to the Array.IndexOf() but it is much more efficient for larger sets.

    0 讨论(0)
提交回复
热议问题