【项目日记(六)】第二层: 中心缓存的具体实现(下)

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:项目日记-高并发内存池⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你做项目
  🔝🔝
开发环境: Visual Studio 2022


在这里插入图片描述

项目日记

  • 1. 前言
  • 2. 中心缓存回收/还回内存的细节
  • 3. 中心缓存回收内存的代码实现
  • 4. 对于页号与span映射的代码补充
  • 5. 总结

1. 前言

本篇文章在上一篇文章的基础
上,对中心缓存的释放内存做补充

上一篇: 中心缓存具体实现(上)

本章重点:

本篇文章着重讲解中心缓存这一层
释放内存的全部过程,包括如何在线程
缓存中回收小块儿内存,以及如何将
自己的大块span内存还给页缓存


2. 中心缓存回收/还回内存的细节

  • 第一步: 当线程缓存中的哈希桶中小块儿内存的个数大于了该线程缓存一次性向中心缓存中申请的小块儿内存的个数,此时小块儿内存会从线程缓存中还回到中心缓存的span中

在这里插入图片描述

细节问题一:

从线程缓存中还回来的小块儿内存是多个,然而中心缓存的桶中可能不止一个span,我们怎么知道哪个小块儿内存对应到哪个span?很明显随意将在小块儿内存还回到任意span肯定是不对的!在上一篇文章中我们提到过如何通过指针得到这块儿空间在程序地址空间上的页号,所以我们可以使用一个unordered_map来存储页号和span的映射关系,当线程缓存还回小块儿内存时,可以通过计算小块儿内存在地址空间的页号来从这个哈希表中找到对应的span,这就是解决了我们的问题!

在这里插入图片描述

  • 第二步:当中心缓存中的span结构体中的成员变量:use_count等于0时,代表这个span被分配出去的小块儿内存都已经还回来了,所以此时将这个span整体还给上一级,也就是页缓存

3. 中心缓存回收内存的代码实现

根据上面的讲解,每还回来一个小块儿
内存都要检查一下它对应的span结构
的use_count是否为0,如果为0就要将
整个span结构还给页缓存!

centralcache.h文件:

void CentralCache::ReleaseListToSpans(void* start, size_t size)//一个桶中有多个span,这些内存块儿属于哪个span是不确定的
{size_t index = AlignmentRule::Index(size);//计算在哪个桶_spanlist[index]._mtx.lock();//要想知道这些内存块分别在哪个span,将内存块的地址除8*1024,得到这个内存块属于第几页while (start != nullptr){void* next = *(void**)start;SpanData* span = PageCache::GetInstance()->MapObjectToSpan(start);//利用地址与span的映射函数,找到这个内存块对应的span*(void**)start = span->_freeList;//将内存块start头插到span中span->_freeList = start;span->_useCount--;//还回来一次内存块,就将usecount--,减到0后就又把内存还给pagecacheif (span->_useCount == 0)//此时说明span切分出去的所有小块儿内存都被还回来了,直接将整个span还给pagecache,pagecache再进行前后页的合并{_spanlist[index].Erase(span);span->_freeList = nullptr;//span中的小块内存已经打乱了,但我知道起始地址和结束地址,可直接置空span->_next = nullptr;span->_prev = nullptr;//还回来内存时不用加桶锁了,但是pagecache的整体大锁需要加上_spanlist[index]._mtx.unlock();PageCache::GetInstance()->_mtx.lock();PageCache::GetInstance()->ReleaseSpanToPageCache(span);PageCache::GetInstance()->_mtx.unlock();_spanlist[index]._mtx.lock();}start = next;}_spanlist[index]._mtx.unlock();
}

注:对于代码的解释都在注释中
并且ReleaseSpanToPageCache函数
是页缓存需要实现的,这里暂时放一放


4. 对于页号与span映射的代码补充

由于这份代码是在pagecache中存放的并且页缓存还没有具体解释,所以看不懂没关系,把页缓存部分学完就都明白了.再一个,存储页号和span的映射关系的哈希表是存储在页缓存中的!因为不止在中心缓存中会使用到这种映射关系,在页缓存时同样页面临相同的问题,所以将它放在了最上层的页缓存中

pagecache.h文件中:

std::unordered_map<PAGE_ID, SpanData*> _idSpanMap;//存储页号和桶中对应的span的映射,解决换回来的内存对应哪个span的问题
//给我一个地址,返回这个地址对应的span
SpanData* PageCache::MapObjectToSpan(void* obj)
{PAGE_ID pageId = (PAGE_ID)obj >> PAGE_SHIFT;//将地址右移13位就算出了页号std::unique_lock<std::mutex> lock(_mtx);//加锁auto ret = _idSpanMap.find(pageId);if (ret != _idSpanMap.end())//若找到了对应的页号,就返回对应的spanreturn _idSpanMap[pageId];else assert(false);//没找到,证明前面的代码有问题assert(ret != nullptr);return ret;
}

5. 总结

中心缓存这一层的所有内容已经讲解完毕,很巧妙的是,中心缓存使用的是桶锁,只有两个不同的线程同时进入到同一个桶中才会有锁竞争问题,这也是这个项目比较快的原因之一.总的来说,中心缓存的作用是承上启下,负责给线程缓存分配切分好的小块儿内存,以及从线程缓存中回收内存.并且它也会向页缓存申请大块儿内存,并且会在合适的时候将大块儿内存还回去,方便页缓存结构进行内存合并!


🔎 下期预告:页缓存的具体实现🔍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/442081.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pycharm删除的文件怎么恢复找回

目录 1、点击被删除文件的所属上级目录右键&#xff1b; 2、弹出的右键菜单点击Local History&#xff0c;Show History 3、打开本地历史界面后&#xff0c;点击误删除文件&#xff1b; 4、在右侧区域&#xff0c;选中文件&#xff0c;点击右键&#xff1b; 5、在右键菜单…

【ArcGIS微课1000例】0099:土地利用变化分析

本实验讲述在ArcGIS软件中基于两期土地利用数据,做土地利用变化分析。 文章目录 一、实验描述二、实验过程三、注意事项一、实验描述 对城市土地利用情况进行分析时,需要考虑不同时期土地利用图层在空间上的差异性,如农用地转建筑用地的空间变化。而该变化过程表现为各时期…

【Android Studio 启动出错】

Android Studio版本&#xff1a;2022.3.1 出错前操作&#xff1a; 昨晚开着三四个项目&#xff0c;然后太晚了直接关机睡觉&#xff0c;第二天起来开机&#xff0c;启动Android Studio&#xff0c;就出现了这个问题&#xff1a; Internal error. Please refer to https://co…

【Tomcat与网络4】Tomcat的连接器设计

目录 1 如何设计一个灵活可靠的连接器 2 主要组件介绍 在上一篇&#xff0c;我们介绍了Tomcat提供服务的整体结构&#xff0c;本文我们一起来看一下Tomcat的连接器的设计。 在前面我们提到Tomcat主要完成两个功能&#xff1a; 处理 Socket 连接&#xff0c;负责网络字节流与…

开源博客项目Blog .NET Core源码学习(8:EasyCaching使用浅析)

开源博客项目Blog使用EasyCaching模块实现缓存功能&#xff0c;主要是在App.Framwork项目中引用了多类包&#xff0c;包括内存缓存&#xff08;EasyCaching.InMemory&#xff09;、Redis缓存&#xff08;EasyCaching.CSRedis&#xff09;&#xff0c;同时支持多种序列化方式&am…

Python采集学习笔记-读取excel数据

表格格式 方法一:使用xlrd import xlrd 1.读取Excel文件 workbook xlrd.open_workbook(plc.xlsx) 2.读取第一个表 sheet workbook.sheet_by_index(0) 3.获取表格总行数 total_rows sheet.nrows 4.创建列表,存储表格一行中每一列信息 plc_info [] for row in range(1…

中国的茶文化:历史、传统与生活

中国的茶文化&#xff1a;历史、传统与生活 一、引言 茶&#xff0c;这一神奇而古老的饮品&#xff0c;与中国的历史、文化和生活方式紧密相连。中国的茶文化&#xff0c;源远流长&#xff0c;博大精深&#xff0c;是中华文明的重要组成部分。它不仅是一种饮料&#xff0c;更是…

Linux 入门基础知识(一)—— Linux的基本使用

Linux 入门基础知识 一、Linux的基本使用和配置1.1、终端1.2、消耗内存1.3、运行级别1.6、登录前欢迎语1.5、登录后欢迎语1.6、shell1.7、ps aux1.8、设置主机名1.9、whoami和who am i1.10、命令提示符 二、Linux执行命令的过程详解和命令类型2.1、命令执行2.2、hash缓存表2.3、…

自托管短链接服务Snapp

什么是 Snapp &#xff1f; Snapp 是一款自托管 URL 缩短服务。能轻松缩短链接。借助 Snapp 的自托管功能&#xff0c;您能拥有完全的控制权&#xff0c;并根据您的要求创建简洁、可共享的链接。 使用 Snapp&#xff0c;您可以个性化链接结尾、监控链接的点击次数&#xff0c;设…

ONLYOFFICE:兼顾协作与安全的开源办公套件

文章目录 前言ONLYOFFICE是什么&#xff1f;ONLYOFFICE的特点多人在线协同灵活集成安全可靠跨平台和设备扩展丰富 实操注册登录编写文档插件安装智谱CopilotDraw.io 新版强势功能显示协作者头像插件 UI 界面更新 总结 前言 随着数字化时代的到来&#xff0c;越来越多的文档处理…

永久删除 Elasticsearch 中的主节点

Elasticsearch 是一个开源分布式搜索和分析引擎&#xff0c;用于各种任务&#xff0c;例如全文搜索、日志分析和实时数据分析。 Elasticsearch 集群由一个或多个节点组成&#xff0c;每个节点可以具有多种角色&#xff0c;包括主节点&#xff08;master node&#xff09;、数据…

橱窗宝石 - 华为OD统一考试

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 橱窗里有一排宝石&#xff0c;不同的宝石对应不同的价格&#xff0c;宝石的价格标记为 gems[i],0<i<n, n gems.length 宝石可同时出售0个或多个&#xff…