文件映射的思考与实验 (映射过大,导致内存使用率非常高)

void ThinkOne::test_multi_file_release_source()
{
    try
    {        
        const size_t fileCount = 256;
        const size_t totalFileBytes = 1024ull * 1024ull * 1024ull * 16ull;
        const size_t fileBytes = totalFileBytes / fileCount;
        HORSE_DEBUG("fileBytes:%llu M", fileBytes / (1024ull * 1024ull));

        std::vector<std::string> fileNameList;
        for (size_t i = 0; i < fileCount; ++i)
        {
            char szBuf[1024] = { 0 };
            _snprintf_s(szBuf, 1024, "d:/files/h_%d.txt", (int)i);
            fileNameList.push_back(szBuf);
        }

        HORSE_DEBUG("createFile begin");
        for (int i = 0; i < fileNameList.size(); ++i)
        {
            if (!createFile(fileNameList[i], fileBytes))
            {
                HORSE_ERROR("createFile failed!");
                return;
            }
        }
        HORSE_DEBUG("createFile end");

        const size_t bytesPerBlock = 1024 * 64;
        const size_t totalCount = fileBytes / bytesPerBlock;
        HORSE_DEBUG("totalCount:%llu", totalCount);

        HORSE_DEBUG("[%s] test ********************", __FUNCTION__);
        std::vector<uint8_t> buf;
        buf.resize(bytesPerBlock + 1); // note: resize

        for (const auto& fileName : fileNameList)
        {
            file_mapping fileMapping(fileName.c_str(), read_write);

            HORSE_DEBUG("memset begin:[%llu,%llu) - %s", 0, totalCount, fileMapping.get_name());
            size_t offset = 0;
            uint8_t* addr = nullptr;
            for (size_t i = 0; i < totalCount; ++i)
            {
                offset = i * bytesPerBlock;
                mapped_region mappedRegion(fileMapping, read_write, offset, bytesPerBlock);
                addr = (uint8_t*)mappedRegion.get_address();

                //write
                memset(addr, 98, bytesPerBlock);

                //read
                //memcpy_s(buf.data(), buf.size(), addr, bytesPerBlock);

                //if (buf[bytesPerBlock - 1] != 98)
                //{
                //    throw 5;
                //}

                //mappedRegion.flush();
            }
            
            HORSE_DEBUG("memset end:[%llu,%llu) - %s", 0, totalCount, fileMapping.get_name());
        }

        HORSE_DEBUG("[%s] end", __FUNCTION__);
    }
    catch (interprocess_exception& e)
    {
        cout << e.what() << endl;
        assert(!"throw interprocess_exception!");
    }

    return;
}

上述代码:

1.测试环境:Win10系统,16G内存

2.映射256个文件,总大小为16G

3.及时释放句柄

发现:

下面所有情况,进程的内存使用都很小

 

1.如果只进行"读"的动作 ,内存占比很小 (资源监视器中:物理内存"已修改"基本为0)

                //read
                memcpy_s(buf.data(), buf.size(), addr, bytesPerBlock);

      耗时: 0:21

2.如果只进行"写"的动作

    (1)如果不及时保存到磁盘上,也就是不调用 mappedRegion.flush(),此种情况内存占比很大

(资源监视器中:物理内存"已修改"基本爆满)

        耗时: 0:21

    (2)如果调用 mappedRegion.flush(),此种情况内存占比很小

(资源监视器中:物理内存"已修改"大约在190M)

        耗时: 1:37

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
主存与缓存之间的地址映射通常使用缓存映射方式来实现。常见的三种映射方式为:直接映射、全相联映射和组相联映射。 1. 直接映射(Direct Mapping): 直接映射是最简单的映射方式,主存中的每个地址只能映射到缓存中的唯一一个位置。主存地址的某些位用于标识缓存行的索引,其余位用于标识缓存行内的字节偏移量。这种映射方式具有低映射开销和较的缓存命中率,但容易产生冲突,导致缓存失效。 2. 全相联映射(Fully Associative Mapping): 全相联映射是最灵活的映射方式,主存中的每个地址可以映射到缓存中的任意位置。主存地址的某些位用于标识缓存行的索引,其余位用于标识缓存行内的字节偏移量。这种映射方式具有较的命中率,但需要更大的硬件开销来实现。 3. 组相联映射(Set Associative Mapping): 组相联映射是直接映射和全相联映射的折中方式,将缓存划分为多个组,每个组中包含多个缓存行。主存地址的某些位用于标识组的索引,另外的位用于标识缓存行内的字节偏移量。在每个组内,使用直接映射的方式进行地址映射。这种映射方式综合了直接映射和全相联映射的优点,能够提供较的命中率和较低的映射开销。 以上是主存与缓存之间常见的地址映射方式。具体的实现方式可能因处理器架构和缓存设计而有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值