programing tip

포함, 존재 및 모든 항목의 성능 벤치마킹

itbloger 2020. 12. 4. 07:57
반응형

포함, 존재 및 모든 항목의 성능 벤치마킹


나는 사이 벤치마킹 성능에 대한 검색되었습니다 Contains, Exists그리고 Any에서 사용할 수있는 방법 List<T>. 나는 항상 이것들 사이에서 혼란 스러웠 기 때문에 호기심에서 이것을 찾고 싶었습니다. SO에 대한 많은 질문은 다음과 같은 이러한 방법의 정의를 설명했습니다.

  1. LINQ Ring : 대규모 컬렉션에 대한 Any () 대 Contains ()
  2. Linq .Any VS .Exists-차이점은 무엇입니까?
  3. LINQ 확장 메서드-Any () 대 Where () 대 Exists ()

그래서 직접하기로 결정했습니다. 나는 그것을 대답으로 추가하고 있습니다. 결과에 대한 더 많은 통찰력이 가장 환영받습니다. 또한 결과를보기 위해 어레이에 대한 벤치마킹을 수행했습니다.


문서에 따르면 :

List.Exists (Object 메서드)

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. ContainsA에 대한이 HashSetO (1)이다.

코드를 가져와 HashSet<int>The performance cost of HashSet<int> set = new HashSet<int>(list);is 거의 제로 에 대한 벤치 마크를 추가했습니다 .

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

이 비교는 Array클래스가 Contains()메서드를 소유하지 않기 때문에 약간 불공평하다는 점을 언급 할 가치가 있습니다 IEnumerable<T>. 순차 통한 확장 메서드를 사용 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.

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.

참고URL : https://stackoverflow.com/questions/18651940/performance-benchmarking-of-contains-exists-and-any

반응형