首先,问题所依据的一些假设:
同步IO: 当我需要进行读取IO操作时,我对文件描述符执行读取系统调用。 CPU 进入特权模式并执行内核代码,这(通过设备驱动程序)要求设备检索我的数据并将我的线程置于
BLOCKED
状态。最后,运行一个调度程序,另一个线程占用我的线程运行的 CPU 内核。READY
(这显然是一个很大的简化)。我的线程现在有机会在内核调度程序运行时被调度。
异步IO: 我执行系统调用,系统调用要求设备检索数据。现在,系统调用不设置线程状态,而是返回一个特殊标记以指示数据尚未准备好。线程继续执行。
我们通常不直接使用这样的系统调用,而是使用一些将回调作为参数的包装函数(由库提供)。该库还生成一个线程,该线程从所有调用(epoll、kqueue ...)中选择文件描述符。一旦某些 fds 可以与该线程交互,就会在某种工作线程线程池(运行事件循环/任务循环)上安排适当的回调。
如果上面的某些地方不对,我很乐意得到纠正!
现在,进入问题:
1。异步 IO 是否有任何性能/资源优势?
据我所知,与完整的上下文切换相比,线程之间的切换非常便宜。如果有足够的工作(将安排另一个线程),CPU 仍将得到充分利用。
以下是我能想到的:
但是我认为还有一些事情可能会损害异步 IO 的性能:
2。反应式编程/协同程序,进一步推进了这个想法(所有代码在工作线程上作为事件运行)是否有任何性能优势?
3。为什么我们实际上做反应式编程?
在我看来,响应式编程在本来应该是开发人员可以处理的抽象(进程和线程)之上构建了一个额外的抽象层,这带来了很多额外的复杂性。 有时这似乎是有道理的,例如,如果我们假设我们想要一个单独的 UI 线程。这样做的问题是,从我的角度来看,这种模式基本上是同步的另一种方法——我们只需启动一个获取 UI 锁的线程就可以完成同样的事情。
我只是看不出传统的并发方法是什么导致了反应式编程框架的创建。
我将非常感谢所有涉及此的解释和来源。