我的问题是与执行同步功能相比,执行异步功能所需的总时间。
我的理解如下:
-异步函数被调用
-执行代码,直到到达等待的代码
-等待代码被执行(例如读取数据库)时,执行线程被释放以执行其他任务
-等待的代码完成后,将分配一个线程来完成此调用
假设我说的是正确的,那么在繁忙的服务器上异步调用是否可能并且通常会比同步调用慢?
我的推理如下:
有一个异步开销(跟踪所有内容)
由于异步代码必须等待线程执行剩余的代码,因此它必须等待线程可用-因此,如果所有线程都忙,它将不得不等待一个? p>
如果这是真的,那么我认为这也意味着,如果有一个等待的方法没有执行任何I / O,它仍将释放执行线程并等待下一个线程可用以完成任务?
更新: 我知道await / async不会使响应时间更快,但是可以使服务器更高效。
我要澄清的要点是,由于异步任务完成时没有可用线程,例如,如果db调用已完成,是否需要等待,是否会使请求完成的时间更长?有更多时间使线程可用?我知道有很多方面需要等待,还有很多要考虑的地方,但是我只是想孤立地理解这一点。
更新2: 假设我有一个设计良好的异步系统,但是我有一种方法,我需要尽可能快且精简-我不希望有任何事情会影响此调用的执行时间。当然,在这种情况下,如果我使该方法异步并释放线程,则调用可能必须等待线程完成才能执行,而如果它是异步的,则该线程将始终在那里等待-在牺牲了其余应用程序的性能?
答案 0 :(得分:3)
- 异步会有开销(跟踪所有内容)
正确。但是,从异步任务获得的速度往往远远超过开销成本,因此可以忽略不计。除非您开始使用 tiny 执行主体对许多任务进行垃圾邮件处理,否则(每个任务)的开销将开始成为明显的因素。
我要澄清的要点是,由于异步任务完成时没有可用线程,例如,如果db调用已完成,是否需要等待,是否会使请求完成的时间更长?线程有更多时间可用?
就目前而言,这是正确的。由于等待任务完成而被搁置的“第一”操作将无法在任务完成的确切时间排成一行。
该操作将不得不重新加入队列,但确实比尚未启动的操作具有更高的优先级。这非常类似于例如邮局的工作方式:
注意:至少我的文化(西欧)是这样处理的。您的里程可能会有所不同。
因此,是的,您的假设实际上是正确的;但我确实要强调,与异步工作的收益相比,此处的时差在天文上可以忽略不计。
如果要挤压特定的操作以获得绝对最快的性能,则必须为其提供自己的线程,而不要让它参与“异步池”计划。但我强烈建议反对,因为这样做的好处将是极度边缘化,并且绝不会超过开发它的复杂性。
第二,请考虑在“精心设计的异步系统”(根据您的问题)中,任务将被分成最小的合理操作,因此单个任务的执行(不包括其间的任何等待时间)将不会有意义。在实践中,您不会注意到必须等待线程可用-除非您使服务器的工作负载大大超支并真正达到了极限-在这一点上,您还需要其他更大的鱼来炒。
假设我有一个设计合理的异步系统,但是我有一种方法需要尽可能的快速和精简-我不希望任何事情会妨碍此调用的执行时间。当然,在这种情况下,如果我使该方法异步并释放线程,则调用可能必须等待线程完成才能执行,而如果它是异步的,则该线程将始终在那里等待-在牺牲了其余应用程序的性能?
我不明白你在这里的理由。
如果在同步示例中假设“线程正在等待我”,则意味着该线程可用并且当前不忙。但是对于您的异步示例,您假设所有线程都处于忙碌状态,并且都不可用。
这些情况完全不同。如果异步应用程序中的所有线程都已饱和,则同步应用程序中的所有线程(一个或多个)也将繁忙。
异步的意图恰恰相反。如果线程当前正在忙碌但处于空闲状态,则在同步应用程序中,您将被迫等待并且无法使用该线程。但是,在异步应用程序中,等待线程将能够在当前处于空闲状态时开始处理您的请求,因为它正在等待另一个尚未完成的任务。
答案 1 :(得分:0)
new ContainerControlledLifetimeManager()
更加注重响应性能。
在客户端UI中,(通常)在单个线程(UI线程)中管理UI。如果您阻止该线程,则UI被阻止。 async-await
提供了一种机制,可以在UI线程之外启动任务,并在该任务完成后在UI线程上恢复执行。该任务可以是IO或CPU密集型的。主要目标是摆脱UI线程。
在服务器(ASP.NET)中,线程池受到限制,因此在执行IO时释放线程使应用程序能够处理更多请求。另一方面,将任务用于CPU密集型工作只会将一个线程池线程换为另一个线程。
所有这些都是额外的工作,很显然,这会占用更多资源(CPU周期和内存)。都是关于响应能力,而不是性能。