【lesson8】高并发内存池Central Cache层释放内存的实现

文章目录

  • Central Cache层释放内存的流程
  • Central Cache层释放内存的实现

Central Cache层释放内存的流程

当thread_cache过长或者线程销毁,则会将内存释放回central cache中的释放回来时–use_count。当use_count减到0时则表示所有对象都回到了span,则将span释放回page cachepage cache中会对前后相邻的空闲页进行合并。

但是这里就有一个问题了,我们如何知道还回来的对象属于哪个span?
其实 对象的地址/8K 就是对应span的地址 为什么呢?
画图理解
画两个span并写出_pageid和计算出地址
在这里插入图片描述
这时又两个对象1和2
假设:
1的地址:FA1000
2的地址:FA3000

除以8k看他们对应的span是否正确。
在这里插入图片描述
从图中可知,之前的结论确实正确。
所以我们接下来只要把_pageId和对应的span进行map映射即可,用map存储对应的_pageId和span
这个map我们设置在page cache中,因为映射关系的写入全部在page cache中进行。

#pragma once#include "Common.h"class PageCache
{
private:SpanList _spanLists[NPAGES];//对应的spanstd::unordered_map<PAGE_ID, Span*> _idSpanMap;PageCache(){}PageCache(const PageCache&) = delete;static PageCache _sInst;
};

而接下来就是建立映射关系,只要有一个span被申请出去,那么我们就要建立映射关系一次
而只有NewSpan可以申请span所以就要修改NewSpan

// 获取一个K页的span
Span* PageCache::NewSpan(size_t k)
{assert(k > 0 && k < NPAGES);// 先检查第k个桶里面有没有spanif (!_spanLists[k].Empty()){Span* kSpan = _spanLists[k]->PopFront();// 建立id和span的映射,方便central cache回收小块内存时,查找对应的span//补充点1:画图补充便于理解for (PAGE_ID i = 0; i < kSpan->_n; ++i){_idSpanMap[kSpan->_pageId + i] = kSpan;}return kSpan;}// 检查一下后面的桶里面有没有span,如果有可以把他它进行切分for (size_t i = k+1; i < NPAGES; ++i){if (!_spanLists[i].Empty()){Span* nSpan = _spanLists[i].PopFront();Span* kSpan = new Span;// 在nSpan的头部切一个k页下来// k页span返回// nSpan再挂到对应映射的位置kSpan->_pageId = nSpan->_pageId;kSpan->_n = k;nSpan->_pageId += k;nSpan->_n -= k;_spanLists[nSpan->_n].PushFront(nSpan);// 存储nSpan的首位页号跟nSpan映射,方便page cache回收内存时// 方便之后进行的合并查找// 补充点2:画图便于理解_idSpanMap[nSpan->_pageId] = nSpan;_idSpanMap[nSpan->_pageId + nSpan->_n - 1] = nSpan;// 建立id和span的映射,方便central cache回收小块内存时,查找对应的spanfor (PAGE_ID i = 0; i < kSpan->_n; ++i){_idSpanMap[kSpan->_pageId + i] = kSpan;}return kSpan;}}// 走到这个位置就说明后面没有大页的span了// 这时就去找堆要一个128页的spanSpan* bigSpan = new Span;void* ptr = SystemAlloc(NPAGES - 1);bigSpan->_pageId = (PAGE_ID)ptr >> PAGE_SHIFT;bigSpan->_n = NPAGES - 1;_spanLists[bigSpan->_n].PushFront(bigSpan);return NewSpan(k);
}

补充点1

 for (PAGE_ID i = 0; i < kSpan->_n; ++i){_idSpanMap[kSpan->_pageId + i] = kSpan;}

上面这段代码逻辑的具象化
在这里插入图片描述
补充点2

_idSpanMap[nSpan->_pageId] = nSpan;
_idSpanMap[nSpan->_pageId + nSpan->_n - 1] = nSpan;

上面代码是把Page Cache中还未使用的span放入map中进行映射以便page cache释放内存是合并
在这里插入图片描述
映射关系存入map中了,接下来Page Cache就要提供一个接口,来为我们查找是否有对应的映射

Span* PageCache::MapObjectToSpan(void* obj)
{//计算映射的页号PAGE_ID id = ((PAGE_ID)obj >> PAGE_SHIFT);//查找是否有该span,有则返回该span//只要没有,则一定是之前写的逻辑出现了问题auto ret = _idSpanMap.find(id);if (ret != _idSpanMap.end()){return ret->second;}else{assert(false);return nullptr;}
}

现在万事具备就只有实现Central Cache的释放流程了

Central Cache层释放内存的实现

void CentralCache::ReleaseListToSpans(void* start, size_t size)
{size_t index = SizeClass::Index(size);_spanLists[index]._mtx.lock();while (start){void* next = NextObj(start);//对象一个一个查找对应的映射关系Span* span = PageCache::GetInstance()->MapObjectToSpan(start);NextObj(start) = span->_freeList;span->_freeList = start;//还回来一个_useCount就减1//补充点1:_useCount++的逻辑span->_useCount--;// _useCount == 0说明span的切分出去的所有小块内存都回来了// 这个span就可以再回收给page cache,pagecache可以再尝试去做前后页的合并if (span->_useCount == 0){//先把span从对应的桶中删除_spanLists[index].Erase(span);//然后清空span中无用的数据span->_freeList = nullptr;span->_next = nullptr;span->_prev = nullptr;// 释放span给page cache时,使用page cache的锁就可以了// 这时把桶锁解掉_spanLists[index]._mtx.unlock();//归还span给Page Cache,让它处理PageCache::GetInstance()->_pageMtx.lock();//调用Page Cache内的释放函数PageCache::GetInstance()->ReleaseSpanToPageCache(span);PageCache::GetInstance()->_pageMtx.unlock();//恢复桶锁解掉_spanLists[index]._mtx.lock();}//走向下一个对象start = next;}_spanLists[index]._mtx.unlock();
}

补充点1:_useCount++的逻辑

// 从中心缓存获取一定数量的对象给thread cache
size_t CentralCache::FetchRangeObj(void*& start, void*& end, size_t batchNum, size_t size)
{size_t index = SizeClass::Index(size);_spanLists[index]._mtx.lock();Span* span = GetOneSpan(_spanLists[index], size);assert(span);assert(span->_freeList);// 从span中获取batchNum个对象// 如果不够batchNum个,有多少拿多少start = span->_freeList;end = start;size_t i = 0;size_t actualNum = 1;while ( i < batchNum - 1 && NextObj(end) != nullptr){end = NextObj(end);++i;++actualNum;}span->_freeList = NextObj(end);NextObj(end) = nullptr;//实际拿了多少个usecount给Thread Cache就加多少span->_useCount += actualNum;_spanLists[index]._mtx.unlock();return actualNum;
}

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

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

相关文章

备战蓝桥杯---数据结构与STL应用(进阶4)

今天主要围绕并查集的一些今典题目展开&#xff1a; 在这里&#xff0c;我们把逻辑真的组合&#xff0c;用并查集即可。一开始&#xff0c;我觉得把a,b,c等价&#xff0c;把第一个赋a,接下来推即可&#xff0c;但这样在判断矛盾时还需要选择合适的点find&#xff0c;于是我们把…

深度学习(10)-Keras项目详解(递归神经网络)

一.递归神经网络基础概念 递归神经网络(Recursive Neural Network, RNN)可以解决有时间序列的问题&#xff0c;处理诸如树、图这样的递归结构。 CNN主要应用在计算机视觉CV中&#xff0c;RNN主要应用在自然语言处理NLP中。 1.h0&#xff0c;h1.....ht对应的是不同输入得到的中…

debian12 解决 github 访问难的问题

可以在 /etc/hosts 文件中添加几个域名与IP对应关系&#xff0c;从而提高 github.com 的访问速度。 据搜索了解&#xff08;不太确定&#xff09;&#xff0c;可以添加这几个域名&#xff1a;github.com&#xff0c;github.global.ssl.fastly.net&#xff0c;github.global.fa…

银河麒麟 aarch64 Mysql环境安装

一、操作系统版本信息 组件版本操作系统Kylin V10 (SP3) /(Lance)-aarch64-Build23/20230324Kernel4.19.90-52.22.v2207.ky10.aarch64MySQLmysql-8.3.0JDK1.8.0_312 二、MySQL下载 官网下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 三、MySQL 安装 3.1 删…

年终奖,还得是腾讯。。。

腾讯年终奖 什么是真正的好公司&#xff1f; 一年到头&#xff0c;出不了几次裁员等劳务纠纷的吃瓜新闻。 只有到年底了&#xff0c;才因为年终奖远高于行业水平&#xff0c;实在没法低调了&#xff0c;"被迫"上热搜。 最近网友爆料了腾讯头牌部门的年终奖&#xff1…

JavaSE——流程控制-循环结构(for循环、while循环、小案例、do-while循环、死循环、循环嵌套)

目录 for循环 while循环 小案例 do-while循环 死循环 循环嵌套 for循环 for(int i 0; i < 5; i) {System.out.println("Hello world"); } 执行的流程&#xff1a; 循环一开始&#xff0c;执行int i0 一次。此时 i 0&#xff0c;接着计算机执行循环条件…

下载RTSP播放器

1.网站1 2.海康播放器 在海康官网上选择【服务支持】【工具软件】&#xff0c;往下滚动&#xff0c;打开VSPlayer_x64

陪女朋友学习计算机二级之栈和队列

栈 栈(堆栈)的定义 堆栈又名栈(stack),它是一种线性表。限定仅在表尾进行插入和删除操作的线性表。是一种后进先出的线性表. 空栈:不含任何元素的空表。 栈顶和栈底 进行插入和删除的这一端(表尾)被称为栈顶&#xff0c;相对地&#xff0c;把另一端称为栈底。 入栈和出栈 …

大小姐驾到!高德地图联合《王者荣耀》推出孙尚香导航语音包

“大小姐驾到&#xff01;统统闪开&#xff01;”如果你是一个手游爱好者&#xff0c;多半会对这句话耳熟能详&#xff0c;来自于国内手游界顶流《王者荣耀》中的高人气角色——孙尚香&#xff0c;并成为一代玩家们的记忆。 如今&#xff0c;随着高德地图与《王者荣耀》达成合…

java之ReentrantLock

在讲RentrantLock之前需要先讲一下AQS和LockSupport&#xff0c;因为rentrantLock底层是用AQS实现的&#xff0c;而AQS中获取阻塞和唤醒底使用LockSupport实现的。 1、LockSupport实现 下面代码中&#xff0c;LockSupport.park方法是当前线程等待&#xff0c;直到获得许可&am…

Istio-解决Zipkin对项目的侵入性问题

Istio采用SideCar模式注入的Enovy代理在某些情况下不能完全解决对项目的无侵入性&#xff0c;比如需要用到Istio的链路追踪功能的时候。需要在代码中手动注入链路追踪需要的header&#xff0c;这样就出现了Istio对业务功能的侵入性。 istio服务网格的调用链跟踪需要依赖在服务之…

大数据环境搭建(一)-Hive

1 hive介绍 由Facebook开源的,用于解决海量结构化日志的数据统计的项目 本质上是将HQL转化为MapReduce、Tez、Spark等程序 Hive表的数据是HDFS上的目录和文件 Hive元数据 metastore&#xff0c;包含Hive表的数据库、表名、列、分区、表类型、表所在目录等。 根据Hive部署模…

axios二次封装用法

axios二次封装 一、request.js import axios from axios import router from "/router";const request axios.create({baseURL: http://localhost:9090,timeout: 5000 })// request 拦截器 // 可以自请求发送前对请求做一些处理 // 比如统一加token&#xff0c;对…

什么是进销存?一文读懂进销存管理系统

阅读本文&#xff0c;你将了解&#xff1a;一、什么是进销存&#xff1b;二、什么是进销存管理系统&#xff1b;三、为什么有必要使用进销存管理系统&#xff1b;四、进销存管理系统的优势&#xff1b;五、好用的进销存管理系统。 这是我们公司搭建好的免费进销存系统模版&…

近屿智能引领行业前沿,精心打造AIGC大模型工程师和产品经理的进阶之路(附完整版学习路径图)

近屿智能&#xff0c;倾力打造了一套独特的AIGC大模型工程师和产品经理学习路径图。该路径图清晰地展示了从初学者到专家水平的技能进阶过程&#xff0c;为工程师和产品经理提供了明确的学习目标和成长路径。 这套学习路径图适用于不同背景和经验的学习者&#xff0c;无论您是初…

GPT在地学、GIS、气象、农业、生态、环境等领域中的高级应用

详情点击公众号&#xff1a;技术科研吧 链接&#xff1a;GPT在地学、GIS、气象、农业、生态、环境等领域中的高级应用 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的强大功能与应用场景 3)国内外经典大模型&#xff08;ChatGPT、LLaMA、Gemini、DAL…

Python创建类的成员并访问

在Python中&#xff0c;类是面向对象编程的核心概念之一。通过类的定义&#xff0c;可以创建对象并定义对象的属性和方法。本文将介绍在Python中如何创建类的成员&#xff08;包括属性和方法&#xff09;&#xff0c;以及如何访问类的成员。 1. 创建类的属性 在Python…

【XR806开发板试用】TCP通信测试 Ping 命令测试

1.工程准备 由于要使用wifi功能&#xff0c;直接从wlan_demo复制一份出来&#xff0c;然后修改。 源文件只留下 main.c 就可以了。 BUILD.gn文件 import("//device/xradio/xr806/liteos_m/config.gni")static_library("app_mying") {configs []sources…

2024美赛C题完整解题教程及代码 网球运动的势头

2024 MCM Problem C: Momentum in Tennis &#xff08;网球运动的势头&#xff09; 注&#xff1a;在网球运动中&#xff0c;"势头"通常指的是比赛中因一系列事件&#xff08;如连续得分&#xff09;而形成的动力或趋势&#xff0c;这可能对比赛结果产生重要影响。球…

STL常用容器—list容器(链表)

STL常用容器—list容器&#xff08;链表&#xff09; 一、list容器基本概念二、list容器基本操作与常用方法1. list构造函数2. ☆list 插入和删除3. list 获取头尾数据4. list 大小操作5. list赋值和交换6. list 反转和排序 三、排序案例 参考博文1: &#xff1c;C&#xff1e;…