【C++项目】高并发内存池第五讲内存回收释放过程介绍

内存回收
- 1.ThreadCache
- 2.CentralCache
- 3.PageCache
项目源代码:高并发内存池
1.ThreadCache
void ThreadCache::Deallocate(void* ptr, size_t size)
{assert(ptr);assert(size <= MAX_BYTES);//计算在哪号桶中,然后插入进去size_t index = SizeClass::Index(size);_freeLists[index].Push(ptr);//当链表长度大于一次批量申请的内存时就开始还一段list给central cacheif (_freeLists[index].Size() >= _freeLists[index].MaxSize()){ListTooLong(_freeLists[index], size);}
}void ThreadCache::ListTooLong(FreeList& list, size_t size)
{void* start = nullptr;void* end = nullptr;list.PopRang(start, end, list.MaxSize());CentralCache::GetInstance()->ReleaseListToSpans(start, size);
}
当闲置的内存超过一个批量单位大小的时候就开始回收,首先要计算出要回收到哪个桶的的内存,然后逐级往上回收。
2.CentralCache
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;span->_usecount--;if (span->_usecount == 0)//说明span切分出去的内存小块都回收回来了,//这时这个span就可以再回收给page cache,page cache可以再尝试去做前后页的合并{_spanLists[index].Erase(span);span->_freeList = nullptr;span->_prev = nullptr;span->_next = nullptr;//释放span给page cache时,使用page cache的锁就可以了//所以需要先把桶锁解掉再加page cache的大锁_spanLists[index]._mtx.unlock();PageCache::GetInstance()->_pageMtx.lock();PageCache::GetInstance()->ReleaseSpanToPageCache(span);PageCache::GetInstance()->_pageMtx.unlock();_spanLists[index]._mtx.lock();}start = next;}_spanLists[index]._mtx.unlock();}
CentralCache回收回来还需要做前后页的合并,合成一个大的内存块,然后继续交给PageCache处理
3.PageCache
void PageCache::ReleaseSpanToPageCache(Span* span)
{//大于128页的span,直接还给堆if (span->_n > NPAGES -1){void* ptr = (void*)(span->_pageId << PAGE_SHIFT);SystemFree(ptr);//delete span;_spanPool.Delete(span);return;}//对span前后的页,尝试进行合并,缓解内存碎片问题(外碎片)//对前后的页进行合并while (1){PAGE_ID prevId = span->_pageId - 1;//auto ret = _idSpanMap.find(prevId);前面的页号没有找到,不进行合并//if (ret == _idSpanMap.end())//{// break;//}auto ret = (Span*)_idSpanMap.get(prevId);if (ret == nullptr){break;}//前面相邻页的span在使用,不进行合并Span* prevSpan = ret;if (prevSpan->_isUse == true){break;}//合并出超过128的span没办法管理,就不能继续合并if (prevSpan->_n + span->_n > NPAGES - 1){break;}//合并span->_pageId = prevSpan->_pageId;span->_n += prevSpan->_n;_spanList[prevSpan->_n].Erase(prevSpan);//delete prevSpan;_spanPool.Delete(prevSpan);}//向后合并while (1){PAGE_ID nextId = span->_pageId + span->_n;/*auto ret = _idSpanMap.find(nextId);if (ret == _idSpanMap.end()){break;}*/auto ret = (Span*)_idSpanMap.get(nextId);if (ret == nullptr){break;}Span* nextSpan = ret;if (nextSpan->_isUse == true){break;}if (span->_n + nextSpan->_n > NPAGES - 1){break;}span->_n += nextSpan->_n;_spanList[nextSpan->_n].Erase(nextSpan);//delete nextSpan;_spanPool.Delete(nextSpan);}_spanList[span->_n].PushFront(span);span->_isUse = false;//_idSpanMap[span->_pageId] = span;_idSpanMap.set(span->_pageId, span);//_idSpanMap[span->_pageId + span->_n - 1] = span;_idSpanMap.set(span->_pageId + span->_n - 1, span);
}
PageCache需要将一页一一页的小块内存何合并成一张大页的内存,来解决内存碎片问题,因为大的可以切成小的,而当申请的内存大于小块的内存碎片时,就会向堆中申请,造成内存浪费。
点赞支持~

相关文章:
【C++项目】高并发内存池第五讲内存回收释放过程介绍
内存回收 1.ThreadCache2.CentralCache3.PageCache 项目源代码:高并发内存池 1.ThreadCache void ThreadCache::Deallocate(void* ptr, size_t size) {assert(ptr);assert(size < MAX_BYTES);//计算在哪号桶中,然后插入进去size_t index SizeClass…...
[毕设记录]@学术工具体验:Sread.ai
我是在查RAG相关的时候,在知乎上面看到了这篇回答:浅谈生成式 AI 技术:检索增强生成 RAG - MarvinZ的文章 - 知乎 https://zhuanlan.zhihu.com/p/659248219 然后在末尾看到了这个 sread.ai 在作者主页看到了他关于这个产品的介绍:…...
uboot - 驱动开发 - 驱动模型
说明 类似于linux,为了规范、统一驱动适配和驱动接口调用,uboot定义了一套驱动模型(Driver Model),简称DM。本文基于:u-boot-2021.10。 优点 为同一类ip的驱动定义了统一的操作接口,DM在软件层面做了一定的抽象。分…...
windows 操作系统命令积累
1. 按 "prt sc" 键 截屏 2. 按 "fn" 键让浏览器进入全屏模式,再次按 "fn" 键让浏览器退出全屏模式( ps:惠普笔记本上是 "fn" "f11" ) 3. ipconfig 查看ip信息 4. 查看指定端口被什么进程占用...
数据结构单链表的实现(C语言)
目录 1.实现的接口和功能2.代码块 1.实现的接口和功能 //打印链表 void SLTPrint(SLTNode** phead); //头插 void PushFont(SLTNode** phead, SLTDataType x); //尾插 void PushBack(SLTNode** phead, SLTDataType x); //头删 void PopFont(SLTNode** phead); //尾删 void Pop…...
Postman的高级使用,傻瓜式学习【下】
目录 前言 1、全局变量、环境变量 1.1、概念: 1.2、如何设置全局变量、环境变量 1.3、获取全局变量、环境变量 1.4、案例1:手动设置变量,请求参数获取 1.5、案例2:代码设置变量,代码获取变量 2、Postman读取外部…...
Qt:关闭对话框,动画实现窗体逐渐缩小到消失
关键技术: 1、使用QPropertyAnimation对象,实现动画效果,逐渐缩小窗体尺寸,以及透明度; 2、在对话框缩小时,要将界面中的控件都隐藏起来,并且将对话框布局的Margin修改成0 代码如下ÿ…...
在Windows上 ciphey安装(详细版)
文章目录 前言 一、不想卸载原有的python版本? 二、安装步骤 1.安装python 2.创建虚拟环境vnev 3.在ciphey的虚拟环境中进行激活 4.安装ciphey 三、参数列表 总结 前言 提示:安装了好几次,但是都没安装成功,我使用了三个电脑p…...
【lesson2】数据库的库操作
文章目录 库操作创建数据库删除数据库字符集和校验规则手动设置字符集和校验集不同字符集和校验集之间的区别修改数据库字符集和校验集备份和恢复数据库 库操作 创建数据库 删除数据库 字符集和校验规则 创建数据库的时候,有两个编码集: 1.数据库编码集…...
Android Studio Giraffe解决gradle reload failed问题
settings.gradle.kts中 pluginManagement {repositories {google()mavenCentral()gradlePluginPortal()} } dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {google()mavenCentral()} } 各增加三行内容&#x…...
刷题笔记day06-哈希表
242.有效的字母异位词 // 思路2:排序后在比较是否相等import ("sort""fmt""io""strings""os" )func isAnagram(s string, t string) bool {s1, s2 : []byte(s), []byte(t)// 从小到大排序sort.Slice(s1, func(i…...
springboot项目中如何实现过滤器鉴权
通常来说鉴权都是写在网关当中,对于单体应用也可以在后台服务中通过一个过滤器实现。其实过程与网关当中的没什么不同,只是在gateway当中目前是基于netty响应式的。过程如下: 一、实现Filter接口 定义自己的过滤器,并且实现Filt…...
【rust/esp32】在idf中使用embedded-graphics控制st7789 LCD屏幕
文章目录 说在前面模块详情准备工作开始编译烧录结果 说在前面 esp32版本:s3运行环境:esp-idf(std)开发环境:wsl2LCD模块:ST7789V2 240*280 LCDgithub地址:这里 模块详情 某宙的esp32s3开发板 某雪的1.69inch LCD模块…...
YOLOv8如何添加注意力模块?
分为两种:有参注意力和无参注意力。 eg: 有参: import torch from torch import nnclass EMA(nn.Module):def __init__(self, channels, factor8):super(EMA, self).__init__()self.groups factorassert channels // self.groups > 0self.softmax …...
用LibreOffice在excel中画折线图
数据表格如下。假设想以x列为横坐标,y1和y2列分别为纵坐标画折线图。 选择插入-》图表: 选择折线图-》点和线,然后点击“下一步”: 选择:列中包含数据序列,然后点击完成(因为图挡住了数据…...
RabbitMQ 链接管理-发布者-消费者
RabbitMQ连接管理器 using RabbitMQ.Client; using System; public class RabbitMQConnectionManager { private readonly IConnectionFactory _connectionFactory; private IConnection _connection; public RabbitMQConnectionManager(string hostName) { …...
JAVA中的垃圾回收器(3)----ZGC
一)ZGC介绍:是JAVA11新引入的低延迟垃圾收集器 ZGC是一款基于Regin的,暂时没有分代概念的,使用了读屏障,颜色指针等技术来实现并发的标记清除和标记整理算法,一低延迟为主要目标的一款垃圾回收器 ZGC的regin可以分为是下图中具有大…...
IDEA 如何运行 SpringBoot 项目
步骤一:配置 Maven 第一步:用 IDEA 打开项目,准备配置 maven 环境 ,当然如果本地没有提前配置好 maven,就用 IDEA 默认的配置即可 配置 maven 步骤 情况 1:如果本地没有配置过 maven,可以保持如…...
Linux MeterSphere测试平台远程访问你不会?来试试这篇文章
🎬 鸽芷咕:个人主页 🔥 个人专栏:《粉丝福利》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言1. 安装MeterSphere2. 本地访问MeterSphere3. 安装 cpolar内网穿透软件4. 配置MeterSphere公网访问地址5. 公网…...
15.k8s集群防火墙配置
防火墙配置 ######################## # master节点防火墙设置 ######################### 所有master节点开放相关防火墙端口 $ firewall-cmd --zonepublic --add-port6443/tcp --permanent $ firewall-cmd --zonepublic --add-port2379-2380/tcp --permanent $ firewall-cmd…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
