我一直在阅读异步IO比同步IO更好的原因,这是因为在同步IO中,您的程序可以继续运行,而同步IO则一直被阻塞,直到操作完成。
我不理解这句话,因为内核使用同步IO (如write())将数据写入磁盘--这不是单独发生的。内核确实需要CPU时间才能做到这一点。
因此,在同步IO中,它也需要它,这可能会导致上下文从我的应用程序切换到内核。所以这并不是真正的阻塞,但是在那里cpu周期确实需要运行这个操作。
同步IO示例:
异步IO的示例:
benefit)
发布于 2021-01-05 00:16:26
我不理解这句话,因为使用同步IO (例如写()),内核会将数据写入磁盘--这不是单独发生的。内核确实需要CPU时间才能做到这一点。
不是的。大多数现代设备能够自行将数据传送到RAM或从RAM中传输数据(使用DMA或总线控制)。
例如,CPU可能告诉磁盘控制器“在地址0x12345000处将4个扇区读入RAM”,然后CPU可以在磁盘控制器完成传输时执行它喜欢的任何其他操作(并且在磁盘控制器完成数据传输时会被磁盘控制器的IRQ中断)。
但是,对于现代系统(您可以有任意数量的进程都希望同时使用同一设备),设备驱动程序必须维护挂起操作的列表。在这种情况下(在加载下);当设备生成一个IRQ来表示它完成了一个操作时,设备驱动程序会通过告诉设备启动下一个“挂起操作”来响应。这样,设备几乎没有空闲时间,等待被要求启动下一个操作(更好的设备利用率),CPU几乎所有的时间都在做其他的事情(在IRQ之间)。
当然,硬件通常是更高级的(例如,拥有内部的操作队列本身,因此驱动程序可以告诉它做多件事情,并且它可以在完成上一次操作后立即启动下一个操作);驱动程序通常是更高级的(例如具有"IO优先级“以确保首先完成更重要的操作,而不仅仅是有一个简单的FIFO队列等待的操作)。
假设我有一个应用程序,它所做的就是获取信息并将其写入文件。使用同步IO而不是同步IO有什么好处吗?
假设您从deviceA (而CPU和deviceB空闲)获得信息;然后处理该信息( deviceA和deviceB空闲);然后将结果写入deviceB (而deviceA和CPU空闲)。您可以看到,大多数硬件大部分时间都什么也不做(利用率很低)。
使用异步IO;当deviceA获取下一段信息时,当deviceB正在编写上一段信息时,CPU可以处理当前信息。在理想的情况下(没有速度不匹配),您可以达到100%的利用率(deviceA、CPU和deviceB从不空闲);即使存在速度不匹配(例如,deviceB需要等待CPU完成当前块的处理),空闲的时间也将被最小化(并尽可能地最大化利用率)。
另一种选择是使用多个任务--例如,一个任务同步从deviceA获取数据,在读取数据时通知另一个任务;第二个任务等待数据到达并处理,然后在处理数据时通知另一个任务;然后第三个任务等待数据处理并同步写入deviceB。这实际上与使用异步IO完全相同(实际上,它可以被认为是“模拟异步IO")。问题是,您增加了一些额外的开销,管理和同步多个任务(在状态和堆栈、任务切换、锁争用等方面花费了更多的RAM );并且使代码变得更加复杂和难以维护。
发布于 2021-01-04 22:08:46
内核确实需要CPU时间才能做到这一点。
是这样吗?
差不多,是的。
是我们认为磁盘访问速度慢的两者之间的区别.在同步IO中,等待将其写入磁盘的时间可以用来继续执行应用程序处理,而将其写入磁盘的核心部分很小吗?
一点儿没错。
假设我有一个应用程序,它所做的就是获取信息并将其写入文件。使用同步IO而不是同步IO有什么好处吗?
取决于许多因素。应用程序如何“获取信息”?CPU密集吗?它是否使用与书写相同的IO?它是一个并发处理多个请求的服务吗?有几个同时连接?表演首先重要吗?在某些情况下:是的,使用异步IO可能有很大的好处。在其他一些情况下,在单独的线程中使用同步IO可以获得大部分好处。在其他情况下,单线程同步IO就足够了。
发布于 2021-01-04 23:39:59
您的理解在一定程度上是正确的,但是您所使用的工具取决于您更喜欢哪种编程模型,而不确定您的程序是否会冻结等待I/O操作完成。对于某些特定的、非常高负载的应用程序,有些模型的效率略高到中等,但除非您处于这种情况下,否则您应该选择这样的模型,使您的程序易于编写和维护,并将其移植到您和您的用户所关心的系统中,而不是某个人正在进行高性能营销的系统。
传统上,有两种方法可以不阻塞地执行I/O:
select (现在的poll;select已经过时,并且存在严重缺陷),这些文件描述符可以读取、输入或接受输出。这需要对尚未准备好处理的部分输入和尚未写出的挂起的输出保持某种显式状态。read/write (甚至是缓冲的stdio函数),并且在其执行上下文的调用帧堆栈/局部变量中隐式地保留任何部分输入或未完成的输出状态。请注意,在上述两个选项中,只有后者才能帮助阻止磁盘访问速度慢,因为根据select/poll,常规文件总是“准备好”输入和输出。
现在有一种趋势,很大程度上是由于像JavaScript这样的语言,倾向于第三种方法,即“异步模型”,甚至还有处理程序回调。与上述任何一种方法相比,我发现更难使用,需要更多的样板代码,更难推理,但很多人都喜欢它。如果您想使用它,最好是使用一个抽象您提到的Linuxisms的库(io_uring等)。因此,您的程序可以在其他系统上运行,而不依赖于最新的Linux流行。
现在来谈谈你的特别问题:
假设我有一个应用程序,它所做的就是获取信息并将其写入文件。使用同步IO而不是同步IO有什么好处吗?
如果您的应用程序只有一个输入源(没有交互性)和单个输出(例如,像大多数unix命令一样),那么任何类型的异步I/O都不会有任何好处,不管是哪种编程思维模型(事件循环、线程、异步回调等等)。最简单、最有效的方法就是读和写。
https://stackoverflow.com/questions/65570336
复制相似问题