为什么cpu绑定更好,阻塞I / O和I / O绑定更好,非阻塞I / O

时间:2016-01-19 13:11:08

标签: blocking nonblocking cpu-speed

我被告知,对于I / O绑定的应用程序,非阻塞I / O会更好。对于CPU绑定应用程序,阻塞I / O要好得多。我找不到这种说法的理由。试过谷歌,但很少有文章只涉及这个话题没有太多细节。有人可以提供深度理由吗?

有了这个,我想澄清一下非阻塞I / O的缺点。

经过另一个线程here之后,我可以理解的一个原因是,如果I / O进程足够重,那么只有我们才能看到使用非阻塞I / O的显着性能改进。它还指出,如果I / O操作的数量很大(典型的Web应用程序场景),其中有许多请求寻找I / O请求,那么我们也看到使用非阻塞I / O的重大改进。

因此,我的问题归结为以下列表:

  1. 如果是CPU密集型应用程序,最好是启动一个 threadpool(或scala的executionContext)并将工作分开 线程池的线程。(我猜它肯定是一个 优于产生自己的线程和分割工作的优势 手动。还使用asyn未来概念,甚至CPU密集型 可以使用回调返回工作,从而避免问题 与阻塞多线程有关?)。如果有I / O也是如此 哪个足够快,然后使用阻塞原则进行I / O. 线程池本身的线程。我是对的吗?

  2. 使用非阻塞的实际缺点或开销是什么 技术上的I / O?为什么我们没有看到使用的性能提升 如果I / O足够快或者非常少,则阻塞I / O. 需要I / O操作?最终它是正在处理的操作系统 I / O的。无论I / O的数量是大还是大 小,让OS处理那种痛苦。这有什么不同。

1 个答案:

答案 0 :(得分:8)

从程序员的角度来看,阻塞I / O比非阻塞I / O更容易使用。您只需调用读/写函数,当它返回时您就完成了。使用非阻塞I / O,您需要检查是否可以读/写,然后读/写然后检查返回值。如果不是所有内容都被读取或写入,则需要再次读取或在写入时可以再次写入的机制。

关于性能:一个线程中的非阻塞I / O并不比阻塞一个线程中的I / O快。 I / O操作的速度由读取或写入的设备(例如硬盘)确定。速度不是由等待(阻塞)或不等待(非阻塞)的人决定的。此外,如果您调用阻塞I / O功能,则操作系统可以非常有效地执行阻止。如果你需要在应用程序中进行阻塞/等待,那么你可能会像操作系统一样好,但你可能也会做得更糟。

那么为什么程序员会更加努力地实现非阻塞I / O?因为,这是关键点,他们的程序除了单一的I / O操作之外还有更多的工作要做。使用阻塞I / O时,您需要等待阻塞I / O完成。使用非阻塞I / O时,您可以执行一些计算,直到阻塞I / O完成。当然,在非阻塞I / O期间,您还可以触发其他I / O(阻塞或非阻塞)。

非阻塞I / O的另一种方法是使用阻塞I / O引入更多线程,但正如SO post that you linked线程中所述,需要付出代价。该成本高于(OS支持的)非阻塞I / O的成本。

如果您的应用程序具有大量I / O但只有低CPU使用率,例如并行拥有大量客户端的Web服务器,那么请使用一些具有非阻塞I / O的线程。通过阻止I / O,您将获得大量线程 - >成本高,所以只使用几个线程 - >需要非阻塞I / O.

如果您的应用程序具有CPU密集型,如读取文件的程序,对完整数据进行密集计算并将结果写入文件,则99%的时间将用于CPU密集型部分。因此,创建一些线程(例如,每个处理器一个)并且并行执行尽可能多的计算。关于I / O,您可能会坚持阻止I / O,因为它更容易实现,并且因为程序无需并行执行。

如果您的应用程序具有CPU密集型和I / O密集型,那么您还可以使用一些线程和非阻塞I / O.你可以想到一个Web服务器,它有很多客户端和网页请求,你在cgi脚本中进行密集计算。在等待连接上的I / O时,程序可以计算另一个连接的结果。或者想一个读取大文件的程序,可以对文件的块进行密集计算(比如计算平均值或者对所有值加1)。在这种情况下,您可以使用非阻塞读取,并在等待下一次读取完成时,您已经可以计算可用的数据。如果结果文件只是一个小的压缩值(如平均值),则可以对结果使用阻塞写入。如果结果文件与输入文件一样大并且类似于"所有值+ 1",那么您可以将结果写回非阻塞,并且在写入完成时您可以自由地对下一个进行计算块。

相关问题