Develop

c# task overhead

작은이야기 2016. 5. 11. 14:01


코드 1


    public class TaskTest

    {

        public static async Task<int> MultiTask(int i)

        {

            if(i == 0)

            {

                return 0;

            }


            Console.Write(" ");

            return await MultiTask(--i);

        }

        public static async Task<int> SingleTask(int i)

        {

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

            {

                Console.Write(" ");

            }

            return i;

        }


        public static async void Test1()

        {

            Console.WriteLine("start");


            List<Int64> multi = new List<long>();

            List<Int64> single = new List<long>();


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

            {

                Stopwatch sw = new Stopwatch();

                sw.Reset();

                sw.Start();

                var ret = await MultiTask(1000);

                sw.Stop();


                multi.Add(sw.ElapsedMilliseconds);

                //Console.WriteLine("m" + sw.ElapsedMilliseconds.ToString());


                sw.Reset();

                sw.Start();

                ret = await SingleTask(1000);

                sw.Stop();


                single.Add(sw.ElapsedMilliseconds);

                //Console.WriteLine("s" + sw.ElapsedMilliseconds.ToString());

            }


            Console.WriteLine("m avg:" + multi.Average());

            Console.WriteLine("s avg:" + single.Average());

        }

    } 

    결과 :
    m avg:32.567
    s avg:32.474


task를 중첩해서 사용했을 때 overhead가 얼마나 있을것인가에 대한 실험인데

제대로 실험이 된건지 잘 모르겠다.


그래서 동시에 다른 스레드들과 섞어서 실험을 해봤다


코드 2


    public class TaskTest

    {

        public static async Task<int> MultiTask(int i, int marker)

        {

            if(i == 0)

            {

                return 0;

            }


            Console.Write(marker);

            return await MultiTask(--i, marker);

        }

        

        public static async Task<int> MultiTask1(int i, int marker)

        {

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

            {

                new Task<int>(() => { Console.Write(marker); return 0; }).Start();

            }


            return 0;

        }

        public static async Task<int> SingleTask(int i, int marker)

        {

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

            {

                Console.Write(marker);

            }

            return i;

        }

        public static int SingleTaskR(int i, int marker)

        {

            if (i == 0)

            {

                return 0;

            }


            Console.Write(marker);

            return SingleTaskR(--i, marker);

        }

        public static int SingleTaskNR(int i, int marker)

        {

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

            {

                Console.Write(marker);

            }

            return i;

        }

        public static async void Test1()

        {

            Console.WriteLine("start");


            List<Int64> multi = new List<long>();

            List<Int64> single = new List<long>();

            List<Int64> singleR = new List<long>();

            List<Int64> singleNR = new List<long>();


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

            {

                var ret2 = MultiTask1(1000, 1);


                Stopwatch sw = new Stopwatch();

                sw.Reset();

                sw.Start();

                var ret = MultiTask(1000, 2);

                sw.Stop();


                multi.Add(sw.ElapsedMilliseconds);

                //Console.WriteLine("m" + sw.ElapsedMilliseconds.ToString());


                Task.WaitAll(new []{ ret2, ret }, 5000);


                Thread.Sleep(500);


                var ret3 = MultiTask1(1000, 3);


                Stopwatch sw1 = new Stopwatch();

                sw1.Reset();

                sw1.Start();

                var ret4 = SingleTask(1000, 4);

                sw1.Stop();


                single.Add(sw1.ElapsedMilliseconds);

                //Console.WriteLine("s" + sw.ElapsedMilliseconds.ToString());


                Task.WaitAll(new[] { ret3, ret4 }, 5000);


                Thread.Sleep(500);


                Stopwatch sw2 = new Stopwatch();

                sw2.Reset();

                sw2.Start();

                SingleTaskR(1000, 5);

                sw2.Stop();


                singleR.Add(sw2.ElapsedMilliseconds);

                

                Stopwatch sw3 = new Stopwatch();

                sw3.Reset();

                sw3.Start();

                SingleTaskR(1000, 6);

                sw3.Stop();


                singleNR.Add(sw3.ElapsedMilliseconds);


            }

            

            Console.WriteLine("m avg:" + multi.Average());

            Console.WriteLine("s avg:" + single.Average());

            Console.WriteLine("sR avg:" + singleR.Average());

            Console.WriteLine("sNR avg:" + singleNR.Average());

        }

    }

    결과 :

    m avg:119.1 

    s avg:92.9 

    sR avg:45.4 

    sNR avg:41.1


출력결과를 보니 적당히 섞여서 실행 되는거 같다.

task가 중첩이 되면 비용이 더 들기는 한가보다


task 없이 재귀가 재귀보다 약 10% 느리고

task 사용하고 재귀가 안재귀보다 약 28% 느리다


task를 사용하면 사용하지 않았을때보다 약 225% 느리다