我的操作系统背景不强,有人可以提供一些例子(如果可能,请在 Go 中),为什么使用缓冲区很重要?
1 回答
假设你在谈论 IO:
想象一下,您有一个var fin *os.File
包裹在缓冲区中的文件,var instrm *bufio.Reader
. 现在假设您正在编写某种解析器,它一次读取输入的一个字符(比如说字节)。包bufio实现了缓冲 I/O。
如果你调用myParser.Parse(fin)
你将调用.Read
4,194,304 次来读取每个字节,这将进行 4,194,304 次系统调用,这将导致 4,194,304 次上下文切换。上下文切换是当控制从用户空间程序转移到操作系统时,是最慢的(非 IO)操作之一。在操作系统没有合并/预取 IO 请求的情况下,您的 IO 设备也极有可能一次寻找和读取一个字节,但是现在大多数操作系统的IO 升降机、预取和设备端缓冲区都阻止了这种情况(但它以大的顺序批量读取总是更好)。
如果您调用myParser.Parse(instrm)
默认bufio.Reader
缓冲区为 4K,您将导致 1,024 次上下文切换(每个系统调用读取 4K 而不是 1 个字节)。由于每个系统调用都有一些开销,这将意味着花费更少的时间进行系统调用和更多的时间让你的程序运行。还值得指出的是,以这种方式运行(没有额外的上下文切换)通常会增加CPU 指令缓存命中率,因为在较小的内存区域内分支会花费更多时间。
缓冲区在网络 IO 等领域甚至很重要,因为它允许您以最大MTU大小发送数据包突发,而不是发送少量的小数据包。
只是不要忘记刷新你的写缓冲区。