串行数据生成-处理流程中能否用mmap优化磁盘IO耗时?
串行流程下使用内存映射文件(mmap)的可行性
完全可以用mmap来优化你的串行场景,而且不会出现你担心的“内存泄漏”问题,具体实现思路和注意事项如下:
核心逻辑:mmap是把磁盘文件映射到进程的内存空间,程序A直接往这个映射区域写数据,内核会自动处理和磁盘的同步。A退出后,映射的文件还留在磁盘上,程序B启动后直接把同一个文件mmap到自己的内存里,就能直接读取数据——如果内核页缓存还保留着这些数据,B甚至不需要再读磁盘,直接从内存取,彻底省掉两次全量磁盘IO的开销。
具体步骤:
- 程序A先创建一个指定路径的文件(临时文件也可以),用
open打开并设置好权限; - 提前用
ftruncate设置文件大小(能预估数据量的话最好,避免后续动态扩容的麻烦); - 调用
mmap把文件映射到自己的内存空间,直接往这块内存写生成的数据; - 数据写完后,调用
msync强制把所有数据同步到磁盘,然后munmap解除映射、关闭文件,正常退出; - 程序B启动后,打开同一个文件,同样用
mmap映射到自己的内存,直接读取处理数据,完成后解除映射、关闭文件,最后可以删掉这个文件。
- 程序A先创建一个指定路径的文件(临时文件也可以),用
关于“内存泄漏”的澄清:
程序A退出后,它的所有内存资源都会被内核自动回收,包括mmap的映射区域。磁盘上的文件只是数据的持久化载体,这根本不算内存泄漏——内存泄漏是进程自己管不住内存,退出后还占着内存,这里完全不存在这个问题。等B处理完删掉文件就行,不会浪费磁盘空间。性能提升点:
A写数据时,内核会用页缓存优化,数据不一定立刻刷到磁盘(除非你强制msync);B读的时候,如果数据还在页缓存里,直接从内存读,等于只做了一次实际的磁盘写入,B的读取完全走内存,速度会快很多。要注意的细节:
- 确保A和B用同一个文件路径,并且文件权限设置正确,双方都能读写;
- 如果数据大小没法提前预估,A可以在写的过程中用
ftruncate动态扩容文件,但可能需要重新调用mmap来扩展映射区域; - A一定要在退出前调用
msync,不然可能有数据没写完就退出的情况,导致B读到不完整的数据; - 如果是一次性的临时数据,B处理完记得删除文件,避免磁盘空间被占用。
内容的提问来源于stack exchange,提问作者snorlax
相关产品推荐
相关产品推荐

