测量 ASP.NET Core 中异步代码与同步代码的性能

2024-02-21

我正在尝试使用 SQL Server Express 和 EF Core 3.1.3 来衡量 ASP.NET Core 3.1 中异步与同步的性能,并且有两个完全相同的函数,除了一个是异步的,一个是同步的:

[HttpGet("search/description/{searchString}")]
public async Task<ActionResult<IEnumerable<Products>>> SearchForProductsDescription(String searchString) {
    return await _context.Products.Where(p => p.Description == searchString).ToListAsync();
}

以及同步版本:

return _context.Products.Where(p => p.Description == searchString).ToList();

我使用 jmeter 作为基准工具,同步函数比异步函数更快(正如预期的那样),但是当我增加 jmeter 中的线程数以使平均响应时间为 500ms


我试图找到一种场景,其中异步函数比同步函数更快,但我遇到了麻烦,是否有什么我出错或误解的地方?

是的。异步代码不是supposed更快。它应该需要更少的线程。如果有 10000 个并发请求,您可能会在同步进程中看到资源(内存、句柄、线程、CPU)耗尽。但在此之前你的数据库就会崩溃。

在 EF 中,异步数据访问并不是为了提高数据访问本身的性能,而是为了符合更喜欢异步 IO 的应用程序框架的要求,例如具有单个 UI 线程的桌面应用程序或使用 ASP.NET Core 的 Web 应用程序。

EF 中的异步有时也可用于并行发送多个查询或在等待长时间运行的数据库操作时运行某些其他代码。

这是一个综合演示,对于大量并发调用,当线程池小于并发请求数时,async 可以快得多。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncDemo
{
    class Program
    {
        static async Task DoStuffAsync()
        {
            await Task.Delay(20);
        }

        static void DoStuffSync()
        {
            Thread.Sleep(20);
        }
        static void Main(string[] args)
        {
            var sw = new Stopwatch();
            List<Task> tasks;
            var iterations = 1000 * 5;

            while (true)
            {
                sw.Restart();
                tasks = new List<Task>();
                for (int i = 0; i < iterations; i++)
                {
                    tasks.Add(Task.Run(() => DoStuffSync()));
                }
                Task.WaitAll(tasks.ToArray());
                Console.WriteLine($"{iterations} sync calls {sw.ElapsedMilliseconds}ms {Process.GetCurrentProcess().Threads.Count} threads");

                tasks = new List<Task>();
                sw.Restart();
                for (int i = 0; i < iterations; i++)
                {
                    tasks.Add(DoStuffAsync());
                }
                Task.WaitAll(tasks.ToArray());
                Console.WriteLine($"{iterations} async calls {sw.ElapsedMilliseconds}ms {Process.GetCurrentProcess().Threads.Count} threads");

            }

        }
    }
}

outputs

5000 sync calls 5546ms 35 threads
5000 async calls 29ms 35 threads
5000 sync calls 3951ms 51 threads
5000 async calls 38ms 51 threads
5000 sync calls 3481ms 52 threads
5000 async calls 29ms 52 threads
5000 sync calls 3320ms 53 threads
5000 async calls 34ms 53 threads
5000 sync calls 3259ms 53 threads
5000 async calls 32ms 53 threads
5000 sync calls 3253ms 53 threads
5000 async calls 33ms 53 threads
5000 sync calls 3321ms 53 threads
5000 async calls 31ms 53 threads
5000 sync calls 3275ms 53 threads
5000 async calls 33ms 53 threads
5000 sync calls 3259ms 51 threads
5000 async calls 28ms 51 threads
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

测量 ASP.NET Core 中异步代码与同步代码的性能 的相关文章

随机推荐