当前位置: 首页 > news >正文

C++项目——高并发内存池(1)--介绍及定长内存池

 1.什么是内存池

1.1 池化技术

将程序中需要经常使用的核心资源先申请出来,放在一个池内,由程序自己管理,这样可以提高资源的使用效率,也可以保证本程序占有的资源数量。

比如之前博文实现的线程池,就是预先的申请出来一些线程,当有任务被推送到任务队列时,线程池内的线程立即开始处理任务,不需要在程序内一次次的创建线程、关闭线程等。

1.2 内存池

普通场景下,当程序长时间运行,或多或少有相关内容会去申请内存资源,由于这些申请的内存块大小不一,会造成大量的内存碎片从而降低程序和操作系统的效率。内存池就是在使用内存空间之前,先整体申请分配一大块内存(内存池),当需要申请内存时,从内存池中取出一块进行动态分配,当该内存被释放时,将释放过后的内存在放回池内,并尽量与周边的空闲内存块合并,以减少外内存碎片,重复利用。若内存池不够时,则自动扩大内存池,从操作系统中申请更大的内存池。

1.2.1 内存池的意义

有两个好处:

  1、由于向内存申请的内存块都是比较大的,所以能够降低外碎片问题。

  2、一次性向内存申请一块大的内存慢慢使用,避免了频繁的向内存请求内存操作,提高内存分配的效率。

1.2.2 内存碎片

外内存碎片

系统经过一系列的分配内存和回收内存,当遇到需要分配一大块内存空间时,剩余内存空间的总数够,但是内存空间不连续,导致无法分配。

内内存碎片

内部碎片是指一个已分配的块比有效载荷大时发生的。(假设以前分配了10个大小的字节,现在只用了5个字节,则剩下的5个字节就会内碎片)。内部碎片的大小就是已经分配的块的大小和他们的有效载荷之差的和。因此内部碎片取决于以前请求内存的模式和分配器实现的模式。

2. 定长内存池

在实现高并发内存池之前,先写一个假定每次申请的内存空间都是固定值的内存池,即定长内存池

介绍:

实现一个 FreeList,每个 FreeList 用于分配固定大小的内存块,比如用于分配 32字节对象的固
定内存分配器等,使用模板,使定长内存池可以根据分配的对象而发生改变。定长内存池中有两个指针, _memory和_freeList 。_memory是指向大块内存的指针,当需要分配内存的时候,他根据(模板类型)字节数,向后移动,将该块内存分配出去。_freeList是指向由还回的内存块的链接而成的链表的头指针。分配时如果内存池中剩余不够,我们就再创建一个新的大块,不必保存前一块大内存的地址,因为如果它始终被占用,申请空间时就用不上它,如果它后续被释放,也会进入_freeList,供我们再次使用。

2.1 定长内存池——回收内存

先上框架

template<class T>
class ObjectPool
{
public://分割内存块 T* New(){}//回收内存void Delete(T* obj) //obj所指向的这一块空间被回收了{}private:char* _memory = nullptr;//指向大块内存的指针size_t _remainBytes = 0;//大块内存存在切分过程中的剩余字节数void* _freeList = nullptr;//还回来的内存块由_freeList指针指向的链表链接起来	
};

由于每个内存块回收后都是放到_freeList里面,形成一个单链表。所以内存块中的起始一部分空间需要变成 一个指针,指向下一个节点。

  • 情况一:当单链表为空的时候,回收一个内存块。首先需要将当前内存块中的第一个指针大小的空间置成nullptr。然后使指向当前内存块的指针作为单链表的头结点。
  • 情况二:当单链表不为空的时候,回收一个内存块。首先如果使用尾插法,那么每次都需要遍历一遍链表,时间复杂度高,所以我们采用头插法。先让当前内存块中的第一个指针大小的空间的置成单链表的头结点,然后将头结点赋给指向当前内存块的指针

问题:我们要想将归还的内存块使用一张链表链接起来,那么这个内存块一定需要大于一个指针的大小!不然我们无法修改内存块的前指针变量个大小的字节,使其指向下一块归还的内存。

但是在32位和64位平台下,指针的大小是不一致的。我们怎么知道使用者处于哪个平台?

针对于这一问题,本质是由于指针变量的大小不确定。但是真正处于某一平台下,指针的大小是唯一的。所以我们不应该显示的规定将前4个或8个字节进行修改,而应该使用一种可以依平台而定的修改方案,即按照当前平台的指针变量大小作为需要修改的字节数。

 采用解引用 (void**)obj || (int**)obj || || (char**)obj

 而非依平台而定解引用 (int*)obj || (long long*)obj

    void Delete(T* obj) //obj所指向的这一块空间被回收了{/*	if (_freelist == nullptr){*(void**)obj = nullptr;_freelist = obj;}else{*(void**)obj = _freelist;_freelist = obj;}发现_freeList是空的时候依然符合 else 所以合并一下*///要回收了 拿析构函数清理一下 obj->~T();* (void**)obj = _freeList;_freeList = obj;}

2.2 定长内存池——分割内存

template<class T>
class ObjectPool
{
public:T* New(){//当剩余的字节数小于需要的字节数,就重新申请一个新的大空间T* obj = nullptr;//优先使用换回来的内存块对象,重复利用if (_freeList){void* next = *(void**)_freeList;//_freeList的前指针大小个字节 解引用为nextobj = (T*)_freeList;_freeList = next;}else{if (_remainBytes < sizeof(T)){_remainBytes = 128 * 1024;_memory = (char*)malloc(128 * 1024);if (_memory == nullptr){throw std::bad_alloc();}}obj = (T*)_memory;_memory += sizeof(T);_remainBytes -= sizeof(T);}//空间有了 初始化一下 定位newnew(obj)T;return obj;}//归还内存void Delete(T* obj){}
private:char* _memory = nullptr;//指向大块内存的指针size_t _remainBytes = 0;//大块内存存在切分过程中的剩余字节数void* _freeList = nullptr;//还回来的内存块由_freeList指针指向的链表链接起来	
};

2.3 测试代码及结果

struct TreeNode
{int _val;TreeNode* _left;TreeNode* _right;TreeNode():_val(0), _left(nullptr), _right(nullptr){}
};void TestObjectPool()
{// 申请释放的轮次const size_t Rounds = 5;// 每轮申请释放多少次const size_t N = 100000;std::vector<TreeNode*> v1;v1.reserve(N);size_t begin1 = clock();//记录使用new和delete场景下的开始时间for (size_t j = 0; j < Rounds; ++j){for (int i = 0; i < N; ++i){v1.push_back(new TreeNode);}for (int i = 0; i < N; ++i){delete v1[i];}v1.clear();}size_t end1 = clock();std::vector<TreeNode*> v2;v2.reserve(N);ObjectPool<TreeNode> TNPool;size_t begin2 = clock();//记录使用定长内存池的New和Delete的开始时间for (size_t j = 0; j < Rounds; ++j){for (int i = 0; i < N; ++i){v2.push_back(TNPool.New());}for (int i = 0; i < N; ++i){TNPool.Delete(v2[i]);}v2.clear();}size_t end2 = clock();cout << "new cost time:" << end1 - begin1 << endl;cout << "object pool cost time:" << end2 - begin2 << endl;
}

相关文章:

C++项目——高并发内存池(1)--介绍及定长内存池

1.什么是内存池 1.1 池化技术 将程序中需要经常使用的核心资源先申请出来&#xff0c;放在一个池内&#xff0c;由程序自己管理&#xff0c;这样可以提高资源的使用效率&#xff0c;也可以保证本程序占有的资源数量。 比如之前博文实现的线程池&#xff0c;就是预先的申请出…...

网络有线无线配置

一、需求 在无线接入区内&#xff0c;当Lsw1的上联口出现故障时&#xff0c;需要通过AP1-LSw1-LSw2-LSw3的路径访问公网server3。这是因为AP1通过无线网连接到LSw1&#xff0c;而LSw1与LSw3之间的链路出现故障&#xff0c;无法直接访问公网server3。因此&#xff0c;流量需要通…...

阅读笔记——Feature-Point Matching for Aerial and Ground Images方法

阅读笔记——Feature-Point Matching for Aerial and Ground Images 1.应用背景 在三维重建应用中&#xff0c;常用的是航空影像&#xff0c;但在城市环境中&#xff0c;面对大量的高层建筑物&#xff0c;航空影像往往不能很好的重建出完整的三维模型。因为航空影像视角约束以…...

前端工程师面试题10条必会笔试题

布局 左边20% 中间自适应 右边200px 不能用定位答案&#xff1a;圣杯布局/双飞翼布局或者flex什么叫优雅降级和渐进增强&#xff1f;渐进增强 progressive enhancement&#xff1a;针对低版本浏览器进行构建页面&#xff0c;保证最基本的功能&#xff0c;然后再针对高级浏览器进…...

【技术分享】Web自动化之Selenium安装

Web 应用程序的验收测试常常涉及一些手工任务&#xff0c;例如打开一个浏览器&#xff0c;并执行一个测试用例中所描述的操作。但是手工执行的任务容易出现人为的错误&#xff0c;也比较费时间。因此&#xff0c;将这些任务自动化&#xff0c;就可以消除人为因素。Selenium 可以…...

【Linux】进程状态的理解

✍作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;Liunx系统编程 本文目录概述两个先行概念我们为啥创建进程Linux下的进程状态1. R 运行状态2.S 休眠状态 --- 可中断休眠状态3. D 磁盘休眠状态 ---不可中断休眠4.T 暂停状态 &#xff08;t 追踪暂停状态&#xff09;5…...

打游戏哪种蓝牙耳机比较好?适合玩游戏的无线蓝牙耳机

2023年耳机市场一如既往地卷&#xff0c;不只是卷音质&#xff0c;还在外观和功能上做了许多的改进&#xff0c;以至于现在哪怕不懂耳机的人从各电商平台都能闭眼入一个款平价品牌耳机且极少会踩雷&#xff0c;玩游戏是当前年轻人的娱乐方式&#xff0c;下面整理了几款适合玩游…...

Fortinet推出新一代自研安全芯片,跨所有网络边缘加速网络与安全融合

专注网络与安全融合的全球网络安全领导者 Fortinet&#xff08;NASDAQ&#xff1a;FTNT&#xff09;&#xff0c;近日宣布推出新一代自研安全芯片 FortiSP5&#xff0c;作为 Fortinet ASIC 技术的最新突破&#xff0c;有力推动了分布式网络边缘安全的重大飞跃。FortiSP5 源自 F…...

ChatGPT爆火背后的真相:学编程已经成为必选项

这一阵最热门的话题&#xff0c;莫过于人工智能新选手——ChatGPT&#xff0c;在推出后只用了两个月就积累了1亿用户&#xff01;它的出现在科技圈掀起了一阵“惊涛骇浪”&#xff0c;有人称ChatGPT的意义&#xff0c;堪比当年蒸汽机的出现&#xff0c;它足以爆发新一轮的“工业…...

Unity UI框架

一、简介 最近在各大网站看了一下 Unity3d 的 UI 框架&#xff0c;各种 UI 框架已经有很多的版本了&#xff0c;各有千秋&#xff0c;有的功能虽然写的完善&#xff0c;但用起来太复杂&#xff0c;有的框架功能不完善&#xff0c;搞个课程就上架了&#xff0c;还有什么 MVC 框…...

vue2提取vue-router的title单独存放,使用i18n实现

成品效果 首先引入i18n(vue-i18n官网文档) 依赖包 npm install vue-i18n8然后单独在src目录下新建一个文件夹lang&#xff0c;存放相对应的变量名称&#xff0c;我这里只做显示中文所以其他引入我都注释了&#xff0c;具体目录如下&#xff1a; src\lang/zh.js部分代码 export…...

【Linux操作系统】【综合实验三 用户帐号、文件系统与系统安全管理】

文章目录一、实验目的二、实验要求三、实验内容四、实验报告要求一、实验目的 要求掌握Linux系统用户的创建、删除与管理操作&#xff1b;熟悉Linux文件系统的管理模式&#xff0c;学会创建用户文件系统并装载和卸载文件系统&#xff1b;掌握超级用户的管理方式与权限&#xf…...

sqlite3数据库-sqlite语句1(五)

DML(Data Manipulation Language,数据操作语言) SELECT:查询表中的数据;SELECT语句中使用WHERE子句SELECT <列名>,... FROM <表名> WHERE <条件表达式>;SELECT id,name,purchase_price FROM Product; /*使用逗号分隔查询多列,顺序同子句顺序*/ SELECT * FROM…...

【图像分类】卷积神经网络之LeNet5网络模型实现MNIST手写数字识别

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 在上一篇博文中我们对LeNet5网络模型的结构进行了剖析,本篇博文,我们将使用PyTorch搭建LeNet5实现MNIST手写数字…...

前端开发环境搭建

文章目录Node.js是什么安装查看版本入门示例NPM使用 npm 命令安装模块常见命令使用淘宝 NPM 镜像TypeScript安装入门示例从github拉取构建项目如何从零创建一个TypeScript项目规划目录结构新建项目Web App运行服务添加依赖打包使用browserify打包使用webpack打包推荐流程目录配…...

学习Flask之四、网页表单

第二章介绍的request对象&#xff0c;使用了客户端请求的所有信息。特别地&#xff0c;request.form提供了对POST请求提交的表单数据的访问。尽管Flask请求对象的支持足于处理网页单&#xff0c;但是还有很多作务很繁锁和重复。两个很好的例子是产生HTML表单代码和验证表单数据…...

CenterMask paper笔记

CenterMask是一个anchor free的实例分割模型&#xff0c; 来自paper: CenterMask: Real-Time Anchor-Free Instance Segmentation 提起anchor free, 会想到FCOS模型&#xff0c;是用来目标检测的&#xff0c; 那么这里就用到了FCOS, 不过换了backbone, 在FCOS检测出目标框后&…...

06- OpenCV查找图像轮廓 (OpenCV基础) (机器视觉)

知识重点 灰度图转换: gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)二值化: 返回两个东西&#xff0c;一个阈值&#xff0c; 一个是二值化的图: thresh, binary cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)查找轮廓: 返回两个结果&#xff0c;分别是轮廓和层级: c…...

OpenGL学习日记之模型绘制

自己编译运行过程中遇到的一些问题 下载Assimp已编译的lib(因为我们公司的电脑有很多权限和限制&#xff0c;也不能自己安装一些没有报备的软件&#xff0c;所以愁方便我就没有用cMake自己编译了)找到一位免费分享的博主的。 https://blog.csdn.net/lady_killer9/article/deta…...

Springboot接口多个DTO入参的Postman上传方式

在Java中使用Spring Boot框架时&#xff0c;可以同时使用多个DTO作为方法参数。 TO&#xff08;Data Transfer Object&#xff09;是一个常见的设计模式&#xff0c;用于封装数据传输对象。它通常用于将数据从一个层传递到另一个层&#xff0c;例如将数据从服务层传递到控制器…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...