非为什么 CPU 绑定与阻塞 I/O 更好,I/O 绑定与非阻塞 I/O 更好



有人告诉我,对于 I/O 绑定应用程序,非阻塞 I/O 会更好。对于 CPU 密集型应用程序,阻塞 I/O 要好得多。我找不到这样说的原因。尝试过谷歌,但很少有文章只是触及主题,没有太多细节。有人能提供深层次的理由吗?

有了这个,我也想弄清楚非阻塞 I/O 的缺点是什么。

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

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

  1. 如果是 CPU 密集型应用程序,是否最好启动线程池(或执行 scala 的上下文)并将工作划分为线程池的线程。(我想它肯定有一个比生成自己的线程和划分工作的优势手动地。还使用未来的异步概念,甚至是CPU密集型概念可以使用回调返回工作,从而避免问题与阻塞多线程有关?此外,如果有 I/O这足够快,然后使用阻塞原则进行 I/O线程池本身的线程。我说的对吗?

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

从程序员的角度来看,阻塞 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 帖子中所述,您链接的线程是有代价的。该成本高于(操作系统支持的)非阻塞 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",那么您可以无阻塞地写回结果,并且在写入完成时,您可以自由地对下一个块进行计算。

最新更新