You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Protobuf FileOutputStream::Flush是否触发fsync将页缓存写入磁盘?

关于protobuf FileOutputStream::Flush()是否触发fsync的问题

你的代码如下:

file_output_ =
    std::make_unique<google::protobuf::io::FileOutputStream>(fd, kDefaultFileBlockSize);
google::protobuf::io::CodedOutputStream coded_output(file_output_.get());
coded_output.WriteLittleEndian32(kProtoSeparator);
int64_t nbytes = message.ByteSizeLong();
coded_output.WriteLittleEndian32(static_cast<int32_t>(nbytes));
CHECK(message.SerializeToCodedStream(&coded_output));
coded_output.Trim();
CHECK(file_output_->Flush());

核心结论

FileOutputStream::Flush()不会触发fsync,它仅会将用户态缓冲区的数据刷新到操作系统的页缓存,不会强制把页缓存写入磁盘。

详细解释

  1. Flush的本质:FileOutputStream的Flush()操作,底层是将自身内部缓冲区中的数据写入内核的页缓存(对应系统调用层面的write(),或是C标准库的fflush())。这一步只是完成了用户态到内核态的数据传递,内核会根据自身的页缓存策略(比如空闲内存、脏页比例、定时刷新等)决定何时将数据真正写入磁盘。

  2. 为什么注释Flush更快:

    • 每次调用Flush()都会触发一次用户态到内核态的切换,并且强制将当前缓冲区的小量数据刷入页缓存,频繁调用会产生大量额外开销。
    • 不调用Flush()时,FileOutputStream会利用你设置的kDefaultFileBlockSize缓冲区攒够足够数据后再一次性写入内核,大幅减少系统调用次数,因此在写入10万条消息时效率更高。
  3. 如何确保数据落盘:如果需要保证数据真正写入磁盘(而非停留在页缓存),你需要在Flush()之后手动调用系统的fsync(fd)或fdatasync(fd)函数,前者会同步文件数据和元数据,后者仅同步文件数据,开销略小。

内容的提问来源于stack exchange,提问作者Liyiping

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 14:14:55