【项目日记(八)】第三层: 页缓存的具体实现(下)

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

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

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

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


在这里插入图片描述

项目日记

  • 1. 前言
  • 2. 什么是内存碎片问题?
  • 3. 地址空间上的内存使用情况
  • 4. 页缓存合并内存的代码实现
  • 5. 总结以及对代码的拓展

1. 前言

请先看完页缓存的具体实现(上)

本章重点:

本篇文章着重讲解页缓存是怎样把从中心缓存中还回来的内存挂在桶上,并且进行前后页的内存合并的,合并内存形成更大的一份内存来减少内存碎片的问题


2. 什么是内存碎片问题?

我们拿整个程序地址空间来举例:

在这里插入图片描述

可以看见虽然整个程序地址空间还有300多byte的空间,但是要申请300byte却申请不出来,对于我们这个项目来说,假设有两个在地址空间中相邻的span,一个是10页,一个是15页,分别挂在第10号桶和第15号桶中,假设没有合并内存此时外部申请一个20页的span是申请不出来的,即使现在空闲的空间有25页,所以这也就体现出了这个项目中合并内存的重要性!


3. 地址空间上的内存使用情况

在地址空间中,一共是4GB大小的空间.
地址从0000 0000到FFFF FFFF.

第0页的起始地址是0
第一页的起始地址是8*1024KB
...以此类推

在这里插入图片描述

当中心缓存还回来一个span后,假设这个span中的大页内存在地址空间中是在第1000页,并且span的大小是50页,那么这个还回来的span就处于空闲状态了,此时我们只需要去检查地址空间中第999页的内存是否空闲,如果空闲就将1000~1050页和999页合并,形成一个51页的大块儿span,并且要不断向前合并直到遇见正在使用的页.同理,需要检查地址空间的1051页是否空闲,如果是空闲的,那么就将它一起合并过去!

在这里插入图片描述


4. 页缓存合并内存的代码实现

在pagecache.h文件中:

void PageCache::ReleaseSpanToPageCache(SpanData* span)
{if (span->_n > N_PAGES - 1)//大于128页的内存直接还给堆,不需要走pagecache{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 prevret = _idSpanMap.find(prevId);if (prevret == _idSpanMap.end())//前面没有页号了break;SpanData* prevspan = ret;if (ret == nullptr)break;if (prevspan->_isUse == true)//前面的页正在使用break;if (prevspan->_n + span->_n > N_PAGES - 1)//当前页数加上span的页数大于128了,pagecache挂不下了break;//开始合并span和span的前面页span->_pageid = prevspan->_pageid;span->_n += prevspan->_n;_spanList[prevspan->_n].Erase(prevspan);//将被合并的页从pagecache中拿下来//delete prevspan;//将prevspan中的数据清除,诸如页号,页数等_spanPool.Delete(prevspan);}while (1)//不断往后合并,直到遇见不能合并的情况{PAGE_ID nextId = span->_pageid + span->_n;auto nextret = _idSpanMap.find(nextId);if (nextret == _idSpanMap.end())//前面没有页号了break;//SpanData* nextspan = nextret->second;auto ret = (SpanData*)_idSpanMap.get(nextId);if (ret == nullptr)break;SpanData* nextspan = ret;if (nextspan->_isUse == true)//前面的页正在使用break;if (nextspan->_n + span->_n > N_PAGES - 1)//当前页数加上span的页数大于128了,pagecache挂不下了break;//开始合并span和span的前面页span->_n += nextspan->_n;_spanList[nextspan->_n].Erase(nextspan);//将被合并的页从pagecache中拿下来//delete nextspan;//将prevspan中的数据清除,诸如页号,页数等_spanPool.Delete(nextspan);}//合并完后将span挂起来_spanList[span->_n].PushFront(span);//合并完后,要重新将这个span的首尾两页的id和这个span进行映射,方便别的span来合并我的时候使用_idSpanMap[span->_pageid] = span;_idSpanMap[span->_pageid + span->_n - 1] = span;span->_isUse = false;
}

对于代码的解释都在注释当中,大家可以发现整个合并内存的过程中,我们已经将delete操作符替换为了定长池中的free,这也就是完全脱离了free函数,并且当合并后的页数大于了128,此时整个页缓存哈希桶是挂不下的,所以要特别注意这一种情况


5. 总结以及对代码的拓展

页缓存结构的讲解已经结束,现在回头来看前面设计的这三层缓存结构,可谓是非常之巧妙,第一层线程缓存是无锁的,申请/释放内存非常高效,而第二层中心缓存是用的桶锁,在大多数情况下也没有竞争锁的问题,效率也非常高,所以现在能理解为什么要设计三层而不是两层,甚至是一层,一方面是为了效率的考量,另一方面是为了可以方便合并相邻的空闲页

对代码的拓展:

在使用到了直接向系统返还内存的函数:

inline static void SystemFree(void* ptr)
{
#ifdef _WIN32VirtualFree(ptr, 0, MEM_RELEASE);
#else// sbrk unmmap等
#endif
}

同样,这份代码知道就行了,不需详谈


🔎 下期预告:项目的测试以及优化🔍

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

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

相关文章

vit细粒度图像分类(九)RAMS-Trans学习笔记

1.摘要 在细粒度图像识别(FGIR)中&#xff0c;区域注意力的定位和放大是一个重要因素&#xff0c;基于卷积神经网络(cnn)的方法对此进行了大量探索。近年来发展起来的视觉变压器(ViT)在计算机视觉任务中取得了可喜的成果。与cnn相比&#xff0c;图像序列化是一种全新的方式。然…

逸学区块链【solidity】真随机数

参考Get a Random Number | Chainlink Documentation 但是很贵&#xff0c;价格 Gas Price&#xff1a;当前gas价格&#xff0c;根据网络状况而波动。Callback gas &#xff1a;返回您所请求的随机值时&#xff0c;回调请求消耗的gas 量。验证gas &#xff1a;量gas 用于验证…

优质成长:新生儿补充维生素B6的关键注意事项

引言&#xff1a; 维生素B6&#xff0c;作为B族维生素的一员&#xff0c;对于新生儿的神经系统发育和代谢功能至关重要。本文将深入探讨维生素B6的作用、新生儿补充的必要性&#xff0c;以及在补充维生素B6时应该注意的事项&#xff0c;为父母提供科学、全面的育儿指南。 第一…

windows pm2 执行 npm脚本或执行yarn脚本遇到的问题及解决方案

环境&#xff1a; 在windows上启动终端来运行一个项目&#xff1b;通过指令npm run start来启动&#xff0c;但是将终端一关&#xff0c;就无法访问了&#xff0c;所以想到用pm2来管理 1. 全局安装pm2 npm i pm2 -g2. 在项目根目录执行指令(大部分兄弟的错误使用方法) pm2 st…

C++初阶:适合新手的手撕string类(模拟实现string类)

上次讲了常用的接口&#xff1a;C初阶&#xff1a;初识STL、String类接口详细讲解&#xff08;万字解析&#xff09; 今天就来进行模拟实现啦 文章目录 1.基本结构与文件规划2.构造函数&#xff08;constructor)2.1构造函数2.1.1无参有参分开2.1.2利用缺省参数合起来 2.2拷贝构…

【Vue.js设计与实现】第二篇:响应系统-阅读笔记(持续更新)

从高层设计的角度去探讨框架需要关注的问题。 系列目录&#xff1a; 标题博客第一篇&#xff1a;框架设计概览【Vue.js设计与实现】第一篇&#xff1a;框架设计概览-阅读笔记第二篇&#xff1a;响应系统【Vue.js设计与实现】第二篇&#xff1a;响应系统-阅读笔记第三篇&#x…

flutter开发实战-ijkplayer视频播放器功能

flutter开发实战-ijkplayer视频播放器功能 使用better_player播放器进行播放视频时候&#xff0c;在Android上会出现解码失败的问题&#xff0c;better_player使用的是video_player&#xff0c;video_player很多视频无法解码。最终采用ijkplayer播放器插件&#xff0c;在flutt…

EasyX图形库学习(二、文字输出)

目录 一、文字绘制函数 字体属性结构体:logfont 文字输出 outtextxy 在指定位置输出字符串。 ​编辑 但如果直接使用,可能有以下报错&#xff1a; 三种解决方案&#xff1a; 将一个int类型的分数,输出到图形界面上 如果直接使用&#xff1a; 会把score输入进去根据A…

Docker基础知识

1、什么是Docker&#xff1f;Docker解决了什么问题 一个项目中&#xff0c;部署时需要依赖于node.js、Redis、RabbitMQ、MySQL等&#xff0c;这些服务部署时所需要的函数库、依赖项各不相同&#xff0c;甚至会有冲突。给部署带来了极大的困难。 所以引入了Docker Docker为了…

MaxKey 单点登录认证系统——登录验证流程分析

客户端依赖包 <dependency><groupId>net.unicon.cas</groupId><artifactId>cas-client-autoconfig-support</artifactId><version>2.3.0-GA</version> </dependency>未登录时 浏览器向客户端发送请求 http://localhost:8989/…

高级Java开发工程师岗位的基本职责(合集)

高级Java开发工程师岗位的基本职责1 职责&#xff1a; 1、负责区块链产品的研发&#xff0c;独立或与团队合作&#xff0c;按时保质完成软件开发项目; 2、参与产品系统设计、概要设计工作&#xff0c;核心功能的代码编写; 3、独立解决和指导其他同事处理开发中遇到的难点问题; …

Qt扩展-muParser数学公式解析

muParser数学公式解析 一、概述1. 针对速度进行了优化2. 支持的运算符3. 支持的函数4. 用户定义的常量5. 用户定义的变量6. 自定义值识别回调7. 其他功能 二、内置函数三、内置二元运算符四、三元运算符五、内置常量六、源码引入1. 源码文件2. 编译器开关1. MUP_BASETYPE2.MUP_…

Unity DOTS中的baking(三)过滤baking的输出

Unity DOTS中的baking&#xff08;三&#xff09;过滤baking的输出 默认情况下&#xff0c;在conversation world&#xff08;baker和baking system运行的环境&#xff09;下产生的所有entities和components&#xff0c;都会作为baking环节的输出。在baking结束时&#xff0c;U…

重写Sylar基于协程的服务器(5、IO协程调度模块的设计)

重写Sylar基于协程的服务器&#xff08;5、IO协程调度模块的设计&#xff09; 重写Sylar基于协程的服务器系列&#xff1a; 重写Sylar基于协程的服务器&#xff08;0、搭建开发环境以及项目框架 || 下载编译简化版Sylar&#xff09; 重写Sylar基于协程的服务器&#xff08;1、…

STM32--USART串口(2)串口外设

一、USART简介 可配置数据位&#xff1a;不需要校验就是8位&#xff0c;需要校验就选9位&#xff1b; 停止位&#xff1a;决定了帧的间隔; STM32F103C8T6USART&#xff1a;USART1挂载在APB2总线上&#xff0c;USART2和USART3挂载在APB1总线上&#xff1b; 二、USART框图 TXE…

STM32外部中断(红外传感器与旋转编码器计数案例)

文章目录 一、介绍部分简介中断系统中断执行流程STM32中断NVIC基本结构NVIC优先级分组外部中断外部中断简介外部中断基本结构外部中断的流程AFIOEXTI框图 相关外设介绍旋转编码器介绍硬件电路对射式红外传感器 二、代码实现对射式红外传感器计次连接电路封装红外传感器与中断函…

Cambalache in Ubuntu

文章目录 前言apt install flatpak这很ok快捷方式后记 前言 gtkmm4相比gtkmm3有很多改革, 代码也干净了许多, 但在windows上开发 有ui设计器那自然方便很多, 但glade又不支持gtkmm4, windows上装Cambalache很是困难. 各种问题都找不到答案.于是 我用VMware虚拟机Ubuntu20.xx安…

探索智慧文旅:科技如何提升游客体验

随着科技的迅猛发展&#xff0c;智慧文旅已成为旅游业的重要发展方向。通过运用先进的信息技术&#xff0c;智慧文旅不仅改变了传统旅游业的运营模式&#xff0c;更在提升游客体验方面取得了显著成效。本文将深入探讨科技如何助力智慧文旅提升游客体验。 一、智慧文旅的兴起与…

React详解

前言 React是一个用于构建用户界面的javaScript库&#xff0c;起源于facebook的内部项目&#xff0c;在13年f进行开源 17版本官网&#xff1a;React – A JavaScript library for building user interfaces 18版本官网&#xff1a;React 官方中文文档 特点&#xff1a; 声…

项目中使用sonar扫码代码

1.在maven的settings.xml配置 org.sonarsource.scanner.maven <profiles> <profile><id>sonar</id><activation><activeByDefault>true</activeByDefault></activation><properties><!-- Optional URL to server. D…