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,它仅会将用户态缓冲区的数据刷新到操作系统的页缓存,不会强制把页缓存写入磁盘。
详细解释
Flush的本质:
FileOutputStream的Flush()操作,底层是将自身内部缓冲区中的数据写入内核的页缓存(对应系统调用层面的write(),或是C标准库的fflush())。这一步只是完成了用户态到内核态的数据传递,内核会根据自身的页缓存策略(比如空闲内存、脏页比例、定时刷新等)决定何时将数据真正写入磁盘。为什么注释Flush更快:
- 每次调用
Flush()都会触发一次用户态到内核态的切换,并且强制将当前缓冲区的小量数据刷入页缓存,频繁调用会产生大量额外开销。 - 不调用
Flush()时,FileOutputStream会利用你设置的kDefaultFileBlockSize缓冲区攒够足够数据后再一次性写入内核,大幅减少系统调用次数,因此在写入10万条消息时效率更高。
- 每次调用
如何确保数据落盘:如果需要保证数据真正写入磁盘(而非停留在页缓存),你需要在
Flush()之后手动调用系统的fsync(fd)或fdatasync(fd)函数,前者会同步文件数据和元数据,后者仅同步文件数据,开销略小。
内容的提问来源于stack exchange,提问作者Liyiping
相关产品推荐
相关产品推荐

