繁体   English   中英

在 c# .net-core web-apis 中使用异步方法的条件

[英]Conditions to use async-methods in c# .net-core web-apis

我正在实现几个小型服务,每个服务都使用实体框架来存储某些(但很少)数据。 它们还具有相当多的业务逻辑,因此将它们彼此分开是有意义的。

我当然知道异步方法和异步等待模式本身可以解决许多性能方面的问题,尤其是在涉及任何 I/O 或 CPU 密集型操作时。

我不确定是否使用实体框架逻辑的异步方法(例如 SaveChangesAsync 或 FirstOrDefaultAsync),因为除了“是我/O 或 CPU 密集型与否?”。

我在研究这个主题时发现了什么(不限于此,但这些都显示了问题):

  • 不使用它可能会导致您的应用程序停止响应,因为线程(不是 cpu 的线程,而是操作系统的虚拟线程)可能会耗尽,因为在这种情况下会阻塞对数据库的 i/o 调用。

  • 由于每种方法的上下文切换,使用它会使您的代码膨胀并降低性能。 特别是当我将这些应用到实体框架调用时,这意味着我至少有三个上下文切换,用于从 controller 到业务逻辑到存储库到数据库的一次调用。

我不知道的,这就是我想从你那里知道的:

  • 有多少个虚拟操作系统线程? 或者更准确地说:如果我希望我的应用程序和服务器能够在 5 秒内处理对此服务的 100 个请求(而且我不希望它们更多,100 个已经被夸大了),我是否应该放弃使用异步/等待那里?

  • 我可以查看哪些精确指标来回答我的任何服务的这个问题?

  • 或者我应该总是使用异步方法来进行 I/O 调用,因为它们已经存在,而且我的服务器上的负载情况总是会发生变化,而且发生了很多事情,异步方法会对我有很大帮助接着就,随即?

我当然知道异步方法和异步等待模式本身可以解决许多性能方面的问题,尤其是在涉及任何 I/O 或 CPU 密集型操作时。

有点。 异步代码的主要好处是它释放了线程。 UI 应用程序(即桌面/移动)在响应速度更快的用户界面中体现了这一优势。 诸如您正在编写的服务之类的服务在更好的可伸缩性方面体现了这种优势——性能优势仅在负载下可见。 此外,服务只能从 I/O 操作中获得这种好处; 无论如何,受 CPU 限制的操作都需要线程,因此在服务应用程序上使用await Task.Run根本没有帮助。

不使用它可能会导致您的应用程序停止响应,因为线程(不是 cpu 的线程,而是操作系统的虚拟线程)可能会耗尽,因为在这种情况下会阻塞对数据库的 i/o 调用。

是的。 更具体地说,线程池的注入率是有限的,所以它只能如此快速地增长。 异步(释放线程)可帮助您的服务处理突发流量和重负载。 报价

请记住,异步代码不会取代线程池。 这不是线程池异步代码; 它是线程池异步代码。 异步代码允许您的应用程序充分利用线程池。 它采用现有的线程池并将其增加到 11。

下一个问题:

由于每种方法的上下文切换,使用它会使您的代码膨胀并降低性能。

async的主要性能缺陷通常与memory相关。 需要分配额外的结构来跟踪正在进行的异步工作。 在同步世界中,线程栈本身就有这些信息。

我不知道,这就是我想从你那里知道的:[我什么时候应该使用异步?]

一般来说,您应该对任何执行基于 I/O 的操作(包括所有 EF 操作)的新代码使用async 基于指标的 arguments 更多的是关于转换async的成本/收益分析 - 即,给定现有的旧同步代码库,在什么时候值得花时间将其转换为async

TLDR:我应该使用异步吗? 是的!

在尝试理解 async/await 时,您似乎陷入了最常见的错误。 异步与多线程正交。

要回答您的问题,您应该什么时候使用异步方法?

If currentContext.IsAsync && method.HasAsyncVersion
    return UseAsync.Yes;
Else
    return UseAsync.No;

以上是短版。

Async/Await 实际上解决了一些问题

  • 解锁 UI 线程
  • M:N 螺纹
  • 多线程调度和同步
  • 基于中断/事件的异步调度

鉴于异步/等待的大量不同用例,您 state 的“假设”仅适用于某些情况。

例如,上下文切换只发生在多线程中。 基于单线程中断的异步实际上通过减少阻塞时间和保持操作系统线程充足的工作来减少上下文切换。

最后,您关于操作系统线程的问题从根本上是错误的。

首先,每个操作系统线程都需要创建一个堆栈(4MB 的连续 RAM,100 个线程意味着在任何工作完成之前需要 400MB 的 RAM)。

其次,除非您的 PC 上有 100 个物理内核,否则您的 CPU 将不得不在每个操作系统线程之间进行上下文切换,从而导致 CPU 在加载该线程时停止。 通过使用 M:N 线程,您可以通过减少操作系统线程的数量并使用绿色线程(dotnet 中的任务)来保持 CPU 运行。

第三,并非所有“等待”都会导致“异步”行为。 任务能够同步返回,短路所有的“膨胀”。

简而言之,如果不深入挖掘,很难通过从异步方法切换到同步方法来找到优化机会。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM