新车
缓存文件写入失败(【C++ 技术分享】写入文件,为啥非要缓存?)

原载于微信公众号:小轻666

前言

本人程序员,会日常分享一些技术笔记。尽量从程序员日常会接触到的东西开始,往深说那么一点。每篇不说多,说多了大家也看不进去。

上一篇聊了,我们的程序里调用 write (fwrite) 写入文件的时候,并没有直接写到磁盘。而是又经历了 2 层缓存,才到磁盘的。如果写程序时不加注意,运行完程序,一拔磁盘,可能会发现磁盘里可能并没有咱写入的内容。(详见上一篇~)

那我们写入文件的时候,有没有可能绕过缓存呢?可以的。今天就来对比下,这两种写入文件的方式。

普通写入方式(Buffered IO)

最常见的写入方式,都是有缓存的,因此也叫 Buffered IO (翻译: “缓冲输入输出”)。

大致如图:

【C++ 技术分享】写入文件,为啥非要缓存?nerror="javascript:errorimg.call(this);">

在默认场景下,我们用的都是这种。

它有啥弊端?

  • 数据额外经历了缓存,也就意味着多一次数据拷贝,消耗了额外的 CPU。
  • 数据在写入磁盘前,都在缓存里,这就占用了额外的内存。

为了避免这些弊端,不用缓存不就行了?可以,那我们来介绍下 direct IO。

Direct IO(直接 IO)

如果没有中间的缓存,一切就很清爽:

【C++ 技术分享】写入文件,为啥非要缓存?nerror="javascript:errorimg.call(this);">

这就是所谓的直接 IO(Direct IO)。

Direct IO 因为不再有缓存,所以:

  • 不再需要将数据从用户空间拷贝到缓存,节省了 CPU。
  • 不需要在内存中维护缓存了,节省了内存。

听起来 direct IO 很美好,而 buffered IO 很愚蠢?那为什么编程时默认都采用 buffered IO 呢?

为什么默认使用 buffered IO?

原因是,和磁盘每交互一次,相比于和内存的交互,都是很慢的。使用 direct IO 的时候,每次写入数据都要直接和磁盘交互,这个交互的频率太高了,这就会导致整体的写入速度很慢。而如果像 buffered IO 这样,把几次要写入的数据缓存起来,再统一和磁盘交互一次,就快得多。

(注:和磁盘的交互是毫秒级别的,和内存的交互是纳秒级别的,差了几个数量级)

请看图:

【C++ 技术分享】写入文件,为啥非要缓存?nerror="javascript:errorimg.call(this);">

也就是说,buffered IO 通过引入缓存,降低了和磁盘交互的频率,提高了数据写入的速度。在绝大多数场景下,buffered IO 的性能都是优于使用 direct IO 的。

因此,它也就成为了默认的写入模式。

Direct IO 有什么用?怎么用?

那 Direct IO 既然慢,还有应用场景吗?

有的。

上面说的 direct IO 慢的原因,就在于其 “高频小量” 写入。

只要我们能通过程序逻辑,不 “高频小量” 的写入,而是每次都写入一块大的数据,就没有上面提到的,和磁盘交互次数过多的问题啦。

在一些场景下,我们的程序里已经攒好了大块大块的数据。这种场景下,就可以通过 direct IO 将数据整块整块的写入磁盘。这样,我们既绕过了 buffered IO 的缓存,节约了 CPU 和内存,同时也不会因为和磁盘交互过多而拖累速度。

举个例子:

一个日志系统,通常为了避免阻塞主程序,会进行 “异步写入”,也就是先把日志内容拷贝到一个缓冲区里,后续再写到磁盘。在这种场景下,在我们一次次调用 “写入日志” 接口的时候,一段一段短小的日志,就会积聚在这个大的缓冲区里。而日志系统,就可以把这些积聚好的内容,整块整块的放入磁盘。这时使用 direct IO,因为每次都放入一大块数据,就不会有速度慢的问题,同时可以比 buffered IO 更加节省 CPU 和内存。

【C++ 技术分享】写入文件,为啥非要缓存?nerror="javascript:errorimg.call(this);">

后续

先总结一下:在大多数场景下,直接用 buffered IO 会比直接用 direct IO 性能更好,但在一些场景下,尤其是程序里已经维护了用户态缓存的情况下,可以通过 direct IO,绕过 page cache 直接写入文件。这样,可以节省 page cache 带来的 CPU 和内存开销。

本篇主要从概念上讲解了 direct IO,从编程实操的角度,还有一些需要注意的地方,请关注后续更新~

另外,除了 buffered IO 和 direct IO,还有其他写入文件的方式,这个也留在后面再聊~

大家有什么想了解的,欢迎留言~


顶一下()     踩一下()

热门推荐

发表评论
0评