简体   繁体   English

C# 中的嵌套等待对性能的影响

[英]Nested awaits in C# impact on performance

I am exposing a method in Api that is expecting a 500 hits from per second.我在 Api 中公开了一种方法,该方法预计每秒有 500 次点击。

I have made all the API's as async to be responsive.我已将所有 API 设为异步以响应。 there could be multiple database calls in each request, should those be async or sync.每个请求中可能有多个数据库调用,应该是异步的还是同步的。

My point is nested awaits let's say 3 levels.我的观点是嵌套等待让我们说 3 个级别。 In such scenario, will it improve performance or the context switching badly affect the performance.在这种情况下,它会提高性能还是上下文切换会严重影响性能。 I have searched enough but i am getting more confuse.我已经搜索了足够多,但我越来越困惑。 There should be some rule of thumbs that i want to follow.我应该遵循一些经验法则。

Also on the bottom, the database call is sync call that i couldn't do much of as already written.同样在底部,数据库调用是同步调用,我不能像已经写的那样做很多事情。

The number of await s isn't usually important. await的数量通常并不重要。 There are some things you can do (eg, using ValueTask<T> instead of Task<T> ) if you find the performance unsuitable.如果您发现性能不合适,您可以做一些事情(例如,使用ValueTask<T>而不是Task<T> )。

However, the big performance problem is here:但是,最大的性能问题在这里:

on the bottom, the database call is sync call在底部,数据库调用是同步调用

If the low-level call is synchronous, then you'll likely have scalability problems.如果低级调用是同步的,那么您可能会遇到可伸缩性问题。 If the current code is doing "async over sync" (eg, Task.Run or Task.Factory.StartNew ), then that would be a problem.如果当前代码正在执行“异步同步”(例如, Task.RunTask.Factory.StartNew ),那么这将是一个问题。 Either change the code to be "async all the way" (ie, make the db call asynchronous) and accept the additional work that needs to be done, or change it to be synchronous all the way and accept the limited scalability of a synchronous solution.要么将代码更改为“一路异步”(即,使 db 调用异步)并接受需要完成的额外工作,要么将其更改为一路同步并接受同步解决方案的有限可扩展性.

The purpose of the asynchronous programming (ie the use of coroutines) is not to introduce performance gain, but to improve the the computing resources when you are not using them.异步编程(即使用协程)的目的不是引入性能增益,而是在您不使用它们时改善计算资源。 Every await you use, introduce a "check point", where the execution might be "suspended".每次await您使用时,都会引入一个“检查点”,执行可能会被“暂停”。

While your logical code is "suspended", the underlying thread is not sleeping like it happens in the synchronous execution model.虽然您的逻辑代码被“挂起”,但底层线程并没有像同步执行 model 中那样休眠。 This is vital for (web)service-based APIs where you can have multiple concurrent requests: when a request is waiting for IO (both network or local), the underlying thread can still progress another request, thus improving the overall throughput of the whole service.这对于基于 (web) 服务的 API 来说至关重要,您可以在其中有多个并发请求:当一个请求正在等待 IO(网络或本地)时,底层线程仍然可以处理另一个请求,从而提高整体的整体吞吐量服务。 Each request does not gain any benefit;每个请求都不会获得任何好处; truly, it gains a little overhead as the compiler rewrites your code into a state machine to handle the "suspension" and "resume".确实,当编译器将您的代码重写为 state 机器以处理“暂停”和“恢复”时,它会增加一些开销。

For this reason, besides from benchmarking, you should choose the granularity of your analysis.因此,除了基准测试之外,您还应该选择分析的粒度。

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

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