我写了关于fwrite VS mmap( “衡量传统I / O与内存映射文件之间的性能折衷的实验”) 的比较学士学位论文。首先,对于写入,您不必去寻找内存映射文件,尤其是大文件。fwrite
是完全可以的,并且几乎总是会优于使用mmap
。mmap
将为您提供最大的并行数据读取性能提升;用于连续数据写入的真正限制fwrite
是硬件。
在我的示例中,remapSize
是文件的初始大小以及每次重新映射时文件增加的大小。fileSize
跟踪文件mappedspace
的大小,表示当前mmap的大小(它的长度),alreadyWrittenBytes
是已经写入文件的字节。
这是示例初始化:
void init() {
fileDescriptor = open(outputPath, O_RDWR | O_CREAT | O_TRUNC, (mode_t) 0600); // Open file
result = ftruncate(fileDescriptor, remapSize); // Init size
fsync(fileDescriptor); // Flush
memoryMappedFile = (char*) mmap64(0, remapSize, PROT_WRITE, MAP_SHARED, fileDescriptor, 0); // Create mmap
fileSize = remapSize; // Store mapped size
mappedspace = remapSize; // Store mapped size
}
我使用了“取消映射-重新映射”机制。
取消映射
这看起来可能如下:
void unmap() {
msync(memoryMappedFile, mappedspace, MS_SYNC); // Flush
munmap(memoryMappedFile, mappedspace)
}
对于 Remap ,您可以选择重新映射整个文件或仅重新映射新添加的部分。
基本上重新映射
完整重映射的示例实现:
void fullRemap() {
ftruncate(fileDescriptor, mappedspace + remapSize); // Make file bigger
fsync(fileDescriptor); // Flush file
memoryMappedFile = (char*) mmap64(0, mappedspace + remapSize, PROT_WRITE, MAP_SHARED, fileDescriptor, 0); // Create new mapping on the bigger file
fileSize += reampSize;
mappedspace += remapSize; // Set mappedspace to new size
}
小重新映射的示例实现:
void smallRemap() {
ftruncate(fileDescriptor, fileSize + remapSize); // Make file bigger
fsync(fileDescriptor); // Flush file
remapAt = alreadyWrittenBytes % pageSize == 0
? alreadyWrittenBytes
: alreadyWrittenBytes - (alreadyWrittenBytes % pageSize); // Adjust remap location to pagesize
memoryMappedFile = (char*) mmap64(0, fileSize + remapSize - remapAt, PROT_WRITE, MAP_SHARED, fileDescriptor, remapAt); // Create memory-map
fileSize += remapSize;
mappedspace = fileSize - remapAt;
}
有一个mremap function
外面,但它指出
该调用是特定于Linux的,不应在旨在可移植的程序中使用。
我不确定我是否明白这一点。如果您想告诉内核“现在加载下一页”,则不行,这是不可能的(至少据我所知)。但是请参阅 广告第3步 ,了解如何建议内核。
您可以madvise
与flag一起使用MADV_SEQUENTIAL
,但请记住,这不会强制内核提前读取,而只是建议您这样做。
男子摘录:
这 导致内核主动预读
请勿mmap
用于顺序数据写入。与使用编写简单的算法相比,它只会导致更多的开销,并且会导致更多的“非自然”代码fwrite
。
这也是我论文期间获得的结果。通过使用mmap
顺序写入,我无法实现任何提速,实际上,这样做总是较慢。