内存映射可以加速磁盘文件的读取速度。
简单说明原理:将磁盘的一段空间映射到内存的地址中,和CPU的交互过程中,减少了缓存申请、缓存释放等过程,所以速度更快。
详细的解释:
一文搞懂内存映射(Memory Map)原理 - 知乎 (zhihu.com)
内存映射的实例代码(Windows)
#include <vector>
#include <iomanip>
#include <iostream>
#include <Windows.h>
bool _saveByMapping(const std::string& filePath, char* dataPtr, const size_t& dataSize)
{
#ifdef _WIN32
HANDLE fh, MapFileH, MapHandle;
fh = CreateFileA((filePath + ".dat").c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE)
{
std::cerr << "[_saveByMapping()] Error in CreateFileA(...)! Path = \"" << filePath << "\"" << std::endl;
return false;
}
MapFileH = CreateFileMappingA(fh, NULL, PAGE_READWRITE, 0, static_cast<DWORD>(dataSize), NULL);
if (MapFileH == NULL)
{
std::cerr << "[_saveByMapping()] Error in CreateFileMappingA(...)! Create size(Byte) = " << dataSize << std::endl;
return false;
}
MapHandle = MapViewOfFile(MapFileH, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (MapHandle == NULL)
{
std::cerr << "[_saveByMapping()] Error in MapViewOfFile(...)!" << std::endl;
return false;
}
else
{
char* pDst = (char*)MapHandle;
std::memcpy(pDst, reinterpret_cast<char*>(dataPtr), dataSize);
}
// release mapping
UnmapViewOfFile(MapHandle);
CloseHandle(MapFileH);
CloseHandle(fh);
return true;
#endif
}
#include <fstream>
bool _saveByStd(const std::string& filePath, char* dataPtr, const size_t& dataSize)
{
#ifdef _WIN32
std::ofstream ofile(filePath.c_str(), std::ios_base::binary);
ofile.write(reinterpret_cast<const char*>(dataPtr), dataSize);
ofile.close();
return true;
#endif
}
#include <chrono>
int main()
{
size_t dataSize = 1024 * 1024 * 1024;
char* dataPtr = new char[dataSize];
{
auto stampBeg = std::chrono::steady_clock::now();
_saveByStd("D:/_saveByStd", dataPtr, dataSize);
auto stampEnd = std::chrono::steady_clock::now();
double time_millisecond = std::chrono::duration<double, std::milli>(stampEnd - stampBeg).count();
std::cout << "_saveByStd, time(millisecond)=" << time_millisecond << std::endl;
}
{
auto stampBeg = std::chrono::steady_clock::now();
_saveByMapping("D:/_saveByMapping", dataPtr, dataSize);
auto stampEnd = std::chrono::steady_clock::now();
double time_millisecond = std::chrono::duration<double, std::milli>(stampEnd - stampBeg).count();
std::cout << "_saveByMapping, time(millisecond)=" << time_millisecond << std::endl;
}
return 0;
}
测试结果
