为什么Tasks,Thread和ThreadPool之间的性能差异如此之大? [英] Why there is so much performance diffrence between Tasks,Thread and ThreadPool?

查看:89
本文介绍了为什么Tasks,Thread和ThreadPool之间的性能差异如此之大?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这里,我附上了我用于性能测试的示例.为什么所有这些之间有如此大的差异? (这是示例控制台应用程序)

Here i attached my example that i used for performance test. Why there is so much diffrence between all this ? (This is sample console application)

class Program
    {
    internal class ThreadObj
        {
        public ManualResetEvent signalComplete { get; set; }
        public int TaskItem { get; set; }
        }

    static void ThreadWork(object o)
        {
        ThreadObj obj = (ThreadObj)o;           
        System.Threading.Thread.Sleep(5000);            
        obj.signalComplete.Set();
        }
    static void Main(string[] args)
        {
        // Using new .net 4.0 Task
        Stopwatch watch = new Stopwatch();
        watch.Start();
        System.Collections.Concurrent.ConcurrentBag<Task> tasks = new System.Collections.Concurrent.ConcurrentBag<Task>();
        Parallel.For(0, 60, i =>
        {
            Task t = Task.Factory.StartNew(() =>
            {                    
                System.Threading.Thread.Sleep(5000);                    
            }, TaskCreationOptions.PreferFairness);
            tasks.Add(t);
        });
        Console.WriteLine("Waiting for task to finish");
        Task.WaitAll(tasks.ToArray());
        watch.Stop();
        Console.WriteLine("Complete(Tasks) : Time " +  watch.ElapsedMilliseconds.ToString());        



        // Using Thread 
        watch.Reset();
        watch.Start();
        System.Collections.Concurrent.ConcurrentBag<ManualResetEvent> tasksThreads = new System.Collections.Concurrent.ConcurrentBag<ManualResetEvent>();
        Parallel.For(0, 60, i =>
        {
            ManualResetEvent signal = new ManualResetEvent(false);
            tasksThreads.Add(signal);
            Thread t = new Thread(new ParameterizedThreadStart(ThreadWork));
            t.Start(new ThreadObj() { signalComplete = signal, TaskItem = i });
        });
        Console.WriteLine("Waiting for task to finish");
        WaitHandle.WaitAll(tasksThreads.ToArray());
        watch.Stop();
        Console.WriteLine("Complete(Threads) : Time " + watch.ElapsedMilliseconds.ToString());


        // Using ThreadPool
        watch.Reset();
        watch.Start();
        System.Collections.Concurrent.ConcurrentBag<ManualResetEvent> tasksThreadPools = new System.Collections.Concurrent.ConcurrentBag<ManualResetEvent>();
        Parallel.For(0, 60, i =>
        {
            ManualResetEvent signal = new ManualResetEvent(false);
            tasksThreadPools.Add(signal);
            ThreadObj obj = new ThreadObj() { signalComplete = signal, TaskItem = i };
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork), obj);
        });
        Console.WriteLine("Waiting for task to finish");
        WaitHandle.WaitAll(tasksThreadPools.ToArray());
        watch.Stop();
        Console.WriteLine("Complete(ThreadPool) : Time " + watch.ElapsedMilliseconds.ToString());
        Console.ReadLine();
        }

    }

请提供您的建议.

这是我得到的样本输出.

Here is sample output that i got.

Waiting for task to finish
Complete(Tasks) : Time 28050
Waiting for task to finish
Complete(Threads) : Time 5435
Waiting for task to finish
Complete(ThreadPool) : Time 15032

推荐答案

您所测试的案例远非一开始就可靠.当您在threadWork方法中执行实际的计算工作时,您会发现结果非常不同. TPL在内部使用线程池,因此这是Threadpool vs Threads的问题.与线程池相比,TPL之所以如此不同的原因很可能是线程池本身的性质(稍后会再介绍).

You're test case is far from solid to begin with. When you perform actual computation work within the threadWork method, you'll find that the results are very different. TPL uses the threadpool internally so it's a matter of Threadpool vs Threads. The reason for the TPL to be so different compared to the Threadpool is likely in the nature of the Threadpool itself (will come back on that one later).

查看线程完成所花费的时间.您的测试方法仅睡眠5秒钟,仅此而已.现在,另一个.43秒去哪了?对,创建和销毁线程本身以及相关的开销(包括上下文切换)是正确的.线程池具有可用于同时执行的线程队列.这取决于线程池,它的配置是在需要时创建和销毁额外的线程.当您在Threadpool中安排60个项目时,Threadpool可能不会创建60个线程来同时处理所有项目,而是使用其中的一小部分并为每个线程处理多个项目.由于您的测试方法只是处于休眠状态,因此可以解释线程所花费的时间与线程池所花费的时间之间的巨大差异.

Look at the time it took for Threads to complete. Your test method only sleeps for 5 seconds, that's it. Now where did the other .43 second go to? Right, to the creation and destruction of the Thread itself and the associated overhead including context switching. The Threadpool has a queue of Threads that can be used to execute simultaneously. It's up to the Threadpool and it's configuration to create and destroy extra threads whenever it deems needed. When you schedule 60 items in the Threadpool , the Threadpool wont likely create 60 threads to handle all items simultaneously but rather use a sub amount of that and handle multiple items per thread. Since your test method is only sleeping, this explains the big difference between the time spent with threads and the time spent with the Threadpool.

由于TPL在内部使用了Threadpool,并且在运行ThreadPool测试之前,因此可以合理地假设:在那个阶段:Threadpool中可用的线程较少,但是由于TPL的运行,创建了更多的线程因此,当您运行Threadpool测试时,最初会有更多可用线程,这说明了TPL和Threadpool之间的区别.

Since TPL uses the Threadpool internally and before you're ThreadPool test ran, it is logical to assume that, at that stage: less threads were available in the Threadpool, but due to the run of the TPL, more threads were created for the Threadpool so in turn, when your Threadpool test ran, there were more threads available initially which explains the difference between TPL and the Threadpool.

实际上,您希望尽可能多地使用Threadpool,尤其是对于计算操作.当您需要与外部资源同步(例如从Web上下载内容)时,我建议不要使用线程,而应使用.NET中提供的更高级的异步选项之一来获取该特定资源.

Practically, you want to use the Threadpool as much as possible, especially for computational operations. When you need to synchronize with an external resource like downloading something from the web, i recommend not using a thread but one of the more advanced async options available in .NET for getting that particular resource.

这篇关于为什么Tasks,Thread和ThreadPool之间的性能差异如此之大?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆