为什么Windows平台下std::fstream比系统API WriteFile速度更快?
结论
你的测试结果差异主要是代码逻辑不对等导致的,其次std::fstream默认确实带有用户态缓冲优化。
核心原因
- 你给
WriteFile加了FILE_FLAG_NO_BUFFERING标志,该标志会完全绕过Windows系统的文件缓存,所有写入直接提交到磁盘,本身性能就远低于走系统缓存的逻辑;而且无缓冲写入对写入大小、内存地址、文件偏移都有强制的扇区对齐要求,你每次仅写入8字节完全不符合规范,Windows为了兼容这类非法调用会额外做大量兼容处理(比如触发读-改-写的扇区操作),进一步大幅拖慢性能。 - 两者的IO行为完全不对等:
std::fstream默认开启了用户态缓冲(通常缓冲区大小为4KB~8KB),你循环调用fstream::write写8字节时,并不会每次都触发系统调用,只是将数据拷贝到fstream的内部缓冲区,等缓冲区满了才会调用一次底层的WriteFile提交到系统。整个测试过程中fstream触发的系统调用次数仅为你写的WriteFile版本的几千分之一,性能自然有数量级的优势。
公平对比的修改方案
如果要让两者测试条件对齐,可以选择以下任意一种修改方式:
- 去掉
CreateFile的FILE_FLAG_NO_BUFFERING标志,使用默认的系统缓存机制,和fstream的默认行为对齐,此时测试得到的WriteFile性能不会弱于std::fstream。 - 如果你需要测试无缓冲写入的性能,需要自己在用户态实现和fstream类似的缓冲逻辑:先把数据攒到一块对齐过的缓冲区中,攒够至少一个扇区大小(通常为512字节或4KB)再调用一次
WriteFile,同时要保证缓冲区地址、写入长度、文件偏移都符合扇区对齐要求,此时无缓冲写入的性能才能达到正常水平。 - 也可以给fstream关闭内部缓冲,比如调用
fs.rdbuf()->pubsetbuf(nullptr, 0),此时fstream的性能会和你当前写的逐次WriteFile版本处于同一水平。
内容的提问来源于stack exchange,提问作者jdt
相关产品推荐
相关产品推荐

