티스토리 뷰

목차

    반응형


    Tuple vs KeyValuePair. 두 항목의 성능(속도와 처리 성능)에 대한 간단한 비교 예제입니다. 이 글을 통해 ui 속도 개선에 도움이 되길 바랍니다.


    8.23 ns -- Allocate Tuple

    0.32 ns -- Allocate KeyValuePair


    1.93 ns -- Pass Tuple as argument

    2.57 ns -- Pass KeyValuePair as argument


    1.91 ns -- Return Tuple

    6.09 ns -- Return KeyValuePair


    2.79 ns -- Load Tuple from List

    4.18 ns -- Load KeyValuePair from List


    4가지 방법으로 간단히 살펴본 결과이며, 기준은 처리 속도 비교입니다. 수행 시간은 나노초입니다.

    아래는 4가지 방법입니다.

    • Allocation : 이 테스트는 인스턴스 생성을 반복합니다. new 키워드가 사용됩니다.
    • Argument : 각 인스턴스는 다른 (non-inline) 함수로 전달됩니다.
    • Return : 각 인스턴스는 다른 함수로 전달된 후 반환됩니다.
    • Load : 각 인스턴스는 다른 함수로 전달되어 List 컬렉션에 저장된 후 반환됩니다.


    예제 소스 다운로드


    Tuple vs KeyValuePair.txt


    using System;

    using System.Collections.Generic;

    using System.Diagnostics;

    using System.Runtime.CompilerServices;

     

    class Program

    {

        static void Main()

        {

        Allocation();

        Argument();

        Return();

        Load();

        Console.Read();

        }

     

        static void Allocation()

        {

        const int max = 1000000;

        var a = new Tuple<string, string>("", "");

        var b = new KeyValuePair<string, string>("", "");

     

        var s1 = Stopwatch.StartNew();

        for (int i = 0; i < max; i++)

        {

            var tuple = new Tuple<string, string>("cat", "dog");

        }

        s1.Stop();

        var s2 = Stopwatch.StartNew();

        for (int i = 0; i < max; i++)

        {

            var pair = new KeyValuePair<string, string>("cat", "dog");

        }

        s2.Stop();

        Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /

            max).ToString("0.00 ns"));

        Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /

            max).ToString("0.00 ns"));

        Console.WriteLine();

        }

     

        static void Argument()

        {

        const int max = 10000000;

        var a = new Tuple<string, string>("", "");

        var b = new KeyValuePair<string, string>("", "");

        X(a);

        X(b);

     

        var s1 = Stopwatch.StartNew();

        for (int i = 0; i < max; i++)

        {

            X(a);

        }

        s1.Stop();

        var s2 = Stopwatch.StartNew();

        for (int i = 0; i < max; i++)

        {

            X(b);

        }

        s2.Stop();

        Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /

            max).ToString("0.00 ns"));

        Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /

            max).ToString("0.00 ns"));

        Console.WriteLine();

        }

     

        static void Return()

        {

        const int max = 10000000;

        var a = new Tuple<string, string>("", "");

        var b = new KeyValuePair<string, string>("", "");

        Y(a);

        Y(b);

     

        var s1 = Stopwatch.StartNew();

        for (int i = 0; i < max; i++)

        {

            Y(a);

        }

        s1.Stop();

        var s2 = Stopwatch.StartNew();

        for (int i = 0; i < max; i++)

        {

            Y(b);

        }

        s2.Stop();

        Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /

            max).ToString("0.00 ns"));

        Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /

            max).ToString("0.00 ns"));

        Console.WriteLine();

        }

     

        static void Load()

        {

        const int max = 10000000;

        var a = new Tuple<string, string>("cat", "dog");

        var b = new KeyValuePair<string, string>("cat", "dog");

        List<Tuple<string, string>> list1 = new List<Tuple<string, string>>();

        list1.Add(a);

        Z(list1);

     

        List<KeyValuePair<string, string>> list2 = new List<KeyValuePair<string, string>>();

        list2.Add(b);

        Z(list2);

     

        var s1 = Stopwatch.StartNew();

        for (int i = 0; i < max; i++)

        {

            Z(list1);

        }

        s1.Stop();

        var s2 = Stopwatch.StartNew();

        for (int i = 0; i < max; i++)

        {

            Z(list2);

        }

        s2.Stop();

        Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /

            max).ToString("0.00 ns"));

        Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /

            max).ToString("0.00 ns"));

        Console.WriteLine();

        }

     

        [MethodImpl(MethodImplOptions.NoInlining)]

        static void X(Tuple<string, string> a)

        {

        }

     

        [MethodImpl(MethodImplOptions.NoInlining)]

        static void X(KeyValuePair<string, string> a)

        {

        }

     

        [MethodImpl(MethodImplOptions.NoInlining)]

        static Tuple<string, string> Y(Tuple<string, string> a)

        {

        return a;

        }

     

        [MethodImpl(MethodImplOptions.NoInlining)]

        static KeyValuePair<string, string> Y(KeyValuePair<string, string> a)

        {

        return a;

        }

     

        static char Z(List<Tuple<string, string>> list)

        {

        return list[0].Item1[0];

        }

     

        static char Z(List<KeyValuePair<string, string>> list)

        {

        return list[0].Key[0];

        }

    }



    return list[0].Key[0];



    속도 비교 결과

     

    8.23 ns

    0.32 ns

     

    1.93 ns

    2.57 ns

     

    1.91 ns

    6.09 ns

     

    2.79 ns

    4.18 ns

    Discussion. 튜플은 할당 성능을 빼곤 KeyValuePair 보다 모든 면에서 빨랐습니다. 따라서, 할당 이외의 작업이 더 많다면 Tuple을 사용하는 것이 더 좋습니다.


    Using structs. 구조체를 사용하는 방법은 좋지 않습니다. 구조체는 모두 데이터 유형이라 모든 호출 과정에서 복사되어 전달하기 때문입니다.


    Summary. 할당 동작은 KeyValuePair가 빨랐으나 나머지에선 Tuple이 더 빨랐습니다. 이렇듯 성능 상의 차이가 있으니 KeyValuePair는 지양하고 Tuple 사용을 지향해야 합니다. ui 속도 개선에 밀접한 관련이 있습니다.


    C# 관련 글


    반응형