内存映射 Windows 示例代码

内存映射可以加速磁盘文件的读取速度。

简单说明原理:将磁盘的一段空间映射到内存的地址中,和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;
    }

    delete[] dataPtr;
    return 0;
}

 

 

测试结果

 

posted @ 2023-07-07 10:58  路边的十元钱硬币  阅读(84)  评论(0编辑  收藏  举报