实验——async什么时候提高吞吐

async是一个语法糖,用来简化异步编程,主要是让异步编程在书写上接近于同步编程。总的来收,在await的时候,相当于附加上了一个.ContinueWith()。

至于为什么async能够提高吞吐,是因为通过async方法返回一个Task对象,IIS缩减了工作线程的处理时间长短(切换到了其他线程,且没有阻塞当前线程),从而提高了单位时间的处理量。这里还有其他的一些细节,详情见这篇博文:

http://www.cnblogs.com/rosanshao/p/3728108.html

关于async的使用,参考这篇博文:

http://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4

博主曾经花了一个下午点时间测试性能,就是没有获得期望的结果,用的就是此博文中举出的反例。当时博主心想“既然TPL中的Task+async就能提高性能,那么为什么EF还要特地的提供XXXAsync方法?这不是让别人更加困惑么?”所以博主就打算不用数据库,简单撸一个Task测一测,看看是不是和我想象中的一般逆天。

根据这篇博客的描述,IIS的线程分为工作线程和IO线程两种,其中工作线程总数被限制在一个阈值,所以减少工作线程的利用效率可以提高吞吐。而在asp.net中,切换线程就分为两种:工作线程->IO线程,工作线程->工作线程(反例)。假定一个工作线程每使用async之前每请求工作1秒,通过切换,IO线程工作的时候,他去处理其他请求,把平均工作时间降为了0.5秒,这样吞吐理想情况下就翻倍了。但是...如果是工作线程->工作线程,虽然对于单个线程而言是减少了,但是其他工作线程又会扔活过来,总体来说没有变化,反而因为交接的问题,性能有所下降...

先用几个负载测试来支持以上言论

首先定义一个提供各种操作的辅助类。

public class BaseFairHelper
    {
        public Task<string> SayHelloTask()
        {
            return Task<string>.Factory.StartNew(() =>
            {
                Thread.Sleep(1000);
                return "Hello";
            });
        }

        public async Task<string> SayHelloAsync()
        {
            return await Task<string>.Factory.StartNew(() =>
            {
                Thread.Sleep(1000);
                return "Hello";
            });
        }

        public string SayHello()
        {
            Thread.Sleep(1000);
            return "Hello";
        }
    }
BaseFairHelper

相关文章: