简体   繁体   English

异步等待增加上下文切换

[英]Does async await increases Context switching

I am aware of how async await works. 我知道异步等待是如何工作的。 I know that when execution reaches to await, it release the thread and after IO completes, it fetches thread from threadpool and run the remaining code. 我知道当执行到达等待时,它释放线程并在IO完成后,它从线程池中获取线程并运行剩余的代码。 This way threads are efficiently utilized. 这样就可以有效地利用线程。 But I am confused in some use cases: 但我在一些用例中感到困惑:

  1. Should we use async methods for the very fast IO method, like cache read/write method? 我们是否应该使用异步方法来实现非常快速的IO方法,比如缓存读/写方法? Would not they result into unnecessarily context switch. 它们不会导致不必要的上下文切换。 If we use sync method, execution will complete on same thread and context switch may not happen. 如果我们使用sync方法,则执行将在同一线程上完成,并且上下文切换可能不会发生。
  2. Does Async-await saves only memory consumption(by creating lesser threads). Async-await是否仅保存内存消耗(通过创建较少的线程)。 Or it also saves cpu as well? 或者它也节省了CPU? As far as I know, in case of sync IO, while IO takes place, thread goes into sleep mode. 据我所知,在同步IO的情况下,当IO发生时,线程进入睡眠模式。 That means it does not consume cpu. 这意味着它不消耗CPU。 Is this understanding correct? 这种理解是否正确?

I am aware of how async await works. 我知道异步等待是如何工作的。

You are not. 你不是。

I know that when execution reaches to await, it release the thread 我知道当执行到达等待时,它会释放线程

It does not. 它不是。 When execution reaches an await, the awaitable operand is evaluated, and then it is checked to see if the operation is complete. 当执行到达等待时,将评估等待的操作数,然后检查操作是否完成。 If it is not, then the remainder of the method is signed up as the continuation of the awaitable, and a task representing the work of the current method is returned to the caller. 如果不是,那么该方法的其余部分被注册为等待的继续,并且表示当前方法的工作的任务被返回给调用者。

None of that is "releasing the thread". 这些都不是“释放线程”。 Rather, control returns to the caller , and the caller keeps executing on the current thread. 相反, 控制返回给调用者 ,调用者继续在当前线程上执行。 Of course, if the current caller was the only thing on this thread, then the thread is done. 当然,如果当前调用者是这个线程上的唯一东西,那么线程就完成了。 But there is no requirement that an async method be the only call on a thread! 但是并不要求异步方法是线程上的唯一调用!

after IO completes IO完成后

An awaitable need not be an IO operation, but let's suppose that it is. 等待的不一定是IO操作,但我们假设它是。

it fetches thread from threadpool and run the remaining code. 它从线程池中获取线程并运行剩余的代码。

No. It schedules the remaining code to run on the correct context . 不会 。它会安排剩余的代码在正确的上下文中运行 That context might be a threadpool thread. 该上下文可能是一个线程池线程。 It might be the UI thread. 它可能是UI线程。 It might be the current thread. 它可能是当前的线程。 It might be any number of things. 它可能是任何数量的东西。

Should we use async methods for the very fast IO method, like cache read/write method? 我们是否应该使用异步方法来实现非常快速的IO方法,比如缓存读/写方法?

The awaitable is evaluated. 等待评估。 If the awaitable knows that it can complete the operation in a reasonable amount of time then it is perfectly within its rights to do the operation and return a completed task. 如果等待者知道它可以在合理的时间内完成操作,则完全有权进行操作并返回完成的任务。 In which case there is no penalty; 在这种情况下,没有罚款; you're just checking a boolean to see if the task is completed. 你只是检查一个布尔值来查看任务是否完成。

Would not they result into unnecessarily context switch. 它们不会导致不必要的上下文切换。

Not necessarily. 不必要。

If we use sync method, execution will complete on same thread and context switch may not happen. 如果我们使用sync方法,则执行将在同一线程上完成,并且上下文切换可能不会发生。

I am confused as to why you think a context switch happens on an IO operation. 我很困惑为什么你认为在IO操作上发生了上下文切换。 IO operations run on hardware, below the level of OS threads. IO操作在硬件上运行,低于OS线程级别。 There's no thread sitting there servicing IO tasks. 没有任何线程可以为IO任务提供服务。

Does Async-await saves only memory consumption(by creating lesser threads) Async-await是否仅保存内存消耗(通过创建较少的线程)

The purpose of await is to (1) make more efficient use of expensive worker threads by allowing workflows to become more asynchronous, and thereby freeing up threads to do work while waiting for high-latency results, and (2) to make the source code for asynchronous workflows resemble the source code for synchronous workflows. 等待的目的是(1)通过允许工作流变得更加异步,从而在等待高延迟结果的同时释放线程来工作,以及(2)制作源代码,从而更有效地使用昂贵的工作线程异步工作流程类似于同步工作流程的源代码。

As far as I know, in case of sync IO, while IO takes place, thread goes into sleep mode. 据我所知,在同步IO的情况下,当IO发生时,线程进入睡眠模式。 That means it does not consume cpu. 这意味着它不消耗CPU。 Is this understanding correct? 这种理解是否正确?

Sure but you have this completely backwards. 当然,你完全倒退了。 YOU WANT TO CONSUME CPU . 你想要消耗CPU You want to be consuming as much CPU as possible all the time! 你想要一直消耗尽可能多的CPU! The CPU is doing work on behalf of the user and if it is idle then its not getting its work done as fast as it could. 该CPU是做代表用户工作 ,如果是闲置那么它没有得到它的工作速度,因为它可以完成。 Don't hire a worker and then pay them to sleep! 不要雇佣工人,然后付钱让他们入睡! Hire a worker, and as soon as they are blocked on a high-latency task, put them to work doing something else so the CPU stays as hot as possible all the time. 雇用一名工人,一旦他们被阻塞在高延迟任务上,就让他们去做其他工作,这样 CPU就会一直保持热度。 The owner of that machine paid good money for that CPU; 该机器的所有者为该CPU支付了很多钱; it should be running at 100% all the time that there is work to be done! 它应该始终以100%运行才能完成工作!

So let's come back to your fundamental question: 那么让我们回到你的基本问题:

Does async await increases Context switching 异步等待增加上下文切换

I know a great way to find out. 我知道一个很好的方法可以找到答案。 Write a program using await, write another one without, run them both , and measure the number of context switches per second. 使用await编写程序,不用编写另一个程序,同时运行它们 ,并测量每秒的上下文切换次数。 Then you'll know. 然后你就会知道。

But I don't see why context switches per second is a relevant metric. 但我不明白为什么每秒上下文切换是一个相关的指标。 Let's consider two banks with lots of customers and lots of employees. 让我们考虑两家拥有大量客户和大量员工的银行。 At bank #1 the employees work on one task until it is complete; 在银行#1,员工完成一项任务直至完成; they never switch context. 他们从不改变背景。 If an employee is blocked on waiting for a result from another, they go to sleep. 如果员工在等待另一个员工的结果时被阻止,他们会进入睡眠状态。 At bank #2, employees switch from one task to another when they are blocked, and are constantly servicing customer requests. 在银行#2,员工在被阻止时从一个任务切换到另一个任务,并且不断地为客户请求提供服务。 Which bank do you think has faster customer service? 您认为哪家银行有更快的客户服务?

Should we use async methods for the very fast IO method, like cache read/write method? 我们是否应该使用异步方法来实现非常快速的IO方法,比如缓存读/写方法?

Such an IO would not block in the classical sense. 这样的IO不会在经典意义上阻止。 "Blocking" is a loosely defined term. “阻止”是一个松散定义的术语。 Normally it means that the CPU must wait for the hardware. 通常,这意味着CPU必须等待硬件。

This type of IO is purely CPU work and there are no context switches. 这种类型的IO纯粹是CPU工作,没有上下文切换。 This would typically happen if the app reads a file or socket slower than data can be provided. 如果应用程序读取文件或套接字的速度慢于可以提供的数据,则通常会发生这种情况。 Here, async IO does not help performance at all. 在这里,异步IO根本无助于性能。 I'm not even sure it would be suitable to unblock the UI thread since all tasks might complete synchronously. 我甚至不确定是否适合解除UI线程的阻塞,因为所有任务可能同步完成。

Or it also saves cpu as well? 或者它也节省了CPU?

It generally increases CPU usage in real-world loads. 它通常会增加实际负载中的CPU使用率。 This is because the async machinery adds processing, allocations and synchronization. 这是因为异步机器增加了处理,分配和同步。 Also, we need to transition to kernel mode two times instead of once (first to initiate the IO, then to dequeue the IO completion notification). 此外,我们需要转换到内核模式两次而不是一次(首先启动IO,然后将IO完成通知出列)。

Typical workloads run with <<100% CPU. 典型工作负载使用<< 100%CPU运行。 A production server with >60% CPU would worry me since there is no margin for error. 具有> 60%CPU的生产服务器会担心我,因为没有错误余量。 In such cases the thread pool work queues are almost always empty. 在这种情况下,线程池工作队列几乎总是空的。 Therefore, there are no context switching savings caused by processing multiple IO completions on one context switch. 因此,在一个上下文切换上处理多个IO完成不会导致上下文切换节省。

That's why CPU usage generally increases (slightly), except if the machine is very high on CPU load and the work queues are often capable of delivering a new item immediately. 这就是为什么CPU使用率通常会增加(略微),除非机器的CPU负载非常高并且工作队列通常能够立即提供新项目。

On the server async IO is mainly useful for saving threads. 在服务器上,异步IO主要用于保存线程。 If you have ample threads available you will realize zero or negative gains. 如果您有足够的线程可用,您将实现零或负增益。 In particular any single IO will not become one bit faster. 特别是任何单个IO都不会快一点。

That means it does not consume cpu. 这意味着它不消耗CPU。

It would be a waste to leave the CPU unavailable while an IO is in progress. 在IO正在进行时,让CPU不可用将是一种浪费。 To the kernel an IO is just a data structure. 对内核而言,IO只是一种数据结构。 While it's in progress there is no CPU work to be done. 在它正在进行的过程中,没有CPU工作要做。

An anonymous person said: 一位匿名人士说:

For IO-bound tasks there may not be a major performance advantage to using separate threads just to wait for a result. 对于IO绑定任务,使用单独的线程来等待结果可能没有主要的性能优势。

Pushing the same work to a different thread certainly does not help with throughput. 将相同的工作推送到不同的线程肯定无助于吞吐量。 This is added work, not reduced work. 这是增加的工作,而不是减少工作。 It's a shell game. 这是一个贝壳游戏。 (And async IO does not use a thread while it's running so all of this is based on a false assumption.) (并且async IO在运行时不使用线程,因此所有这些都基于错误的假设。)

A simple way to convince yourself that async IO generally costs more CPU than sync IO is to run a simple TCP ping/pong benchmark sync and async. 一个简单的方法来说服自己异步IO通常比同步IO花费更多的CPU是运行简单的TCP ping / pong基准同步和异步。 Sync is faster. 同步更快。 This is kind of an artificial load so it's just a hint at what's going on and not a comprehensive measurement. 这是一种人为的负载,所以它只是暗示正在发生的事情,而不是一个全面的测量。

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

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