【C++项目】高并发内存池第一讲(项目整体框架介绍、哈系统结构设计)

news2024/10/4 18:19:03

0

高并发内存池项目第一讲

  • 一、高并内存池概念
  • 二、项目介绍
  • 三、项目细节
  • 四.哈系统结构设计

一、高并内存池概念

内存池(Memory Pool) 是一种动态内存分配与管理技术。 通常情况下,程序员习惯直接使用 new、delete、malloc、free 等API申请分配和释放内存,这样导致的后果是:当程序长时间运行时,由于所申请内存块的大小不定,频繁使用时会造成大量的内存碎片从而降低程序和操作系统的性能。内存池则是在真正使用内存之前,先申请分配一大块内存(内存池)留作备用,当程序员申请内存时,从池中取出一块动态分配,当程序员释放内存时,将释放的内存再放入池内,再次申请池可以 再取出来使用,并尽量与周边的空闲内存块合并。若内存池不够时,则自动扩大内存池,从操作系统中申请更大的内存池。

  • 由于现在硬件条件已经很成熟,大多数运行环境都是多核的,为了提高效率,则高并发这一情况应运而生,对于高并发内存池,则是基于多线程并发申请使用的一个内存池称为高并发内存池。

二、项目介绍

本项目参考了谷歌 tcmalloc 设计模式,设计实现了高并发的内存池。基于 win10 环境 VS2013,采用 C++进行编程,池化技术、多线程、TLS、单例模式、互斥锁、链表、哈希等数据结构。该项目利用了 thread cache、central、cache、page cache 三级缓存结构,基于多线程申请释放内存的场景,最大程度提高了效率,解决了绝大部分内存碎片问题。
0001

三、项目细节

(一)项目设计目标
现代很多的开发环境都是多核多线程,在申请内存的场景下,必然存在激烈的锁竞争问题。所以这次我们实现的内存池需要考虑以下几方面的问题。

  1. 内存碎片问题。
  2. 性能问题。
  3. 多核多线程环境下,锁竞争问题。
    0002

(二)项目结构
concurrent memory pool主要由线程缓存(threadcache)、中心缓存(centralcache)、页缓存(pagecache)3个部分构成,如下图
000

四.哈系统结构设计

0003

  • 自由链表结构:
    0005

  • 内存对齐规则
    这是目前比较优化的算法 内存最多浪费在10%左右

	/*
	*   [1,128]                                8byte对齐             freelist[0,16)
	    [128 + 1, 1024]	                   16byte对齐           freelist[16, 72) 
	    [1024 + 1, 8 * 1024]            128byte对齐         freelist[72, 128) 
		[8 * 1024 + 1, 64 * 1024]     1024byte对齐	     freelist[128, 184)     
		[64 * 1024 + 1, 256 * 1024]   8 * 1024byte对齐  freelist[184, 208)
	*/
  • 头删和头插结构
    0006

  • 代码:

#pragma once
#include<vector>
#include<iostream>
#include<time.h>
#include<assert.h>
static const size_t MAX_BYTES = 1024 * 256;//设置最大可以申请的内存数
void*& NextObj(void* obj)
{
	return *(void**)obj;//取到这块内存的前4或8字节的位置 存放freeList指针
}

//管理切分好的小对象内存块
class FreeList
{
	void Push(void* obj)//插入
	{
		assert(obj);
		//头插
		NextObj(obj) = _freeList;
		_freeList = obj;//更新头节点
	}

	void* Pop()
	{
		assert(_freeList);
		//头删
		void* obj = _freeList;
		_freeList = NextObj(obj); //这里的Next(Obj)存的是obj后面挂着的链表的地址
	}
private:
	void* _freeList;
};

//计算对象大小的对齐规则
class SizeClass
{
	//优化算法:
	//整体控制在最多10%左右的内碎片浪费// [1,128]
	/*
	*   [1,128]                                8byte对齐             freelist[0,16)
	    [128 + 1, 1024]	                   16byte对齐           freelist[16, 72) 
	    [1024 + 1, 8 * 1024]            128byte对齐         freelist[72, 128) 
		[8 * 1024 + 1, 64 * 1024]     1024byte对齐	     freelist[128, 184)     
		[64 * 1024 + 1, 256 * 1024]   8 * 1024byte对齐  freelist[184, 208)
	*/

	//内联函数:调用频繁,因此写成内联函数
	static inline size_t _RoundUp(size_t size, size_t AlignNum)
	{
		size_t AlignSize = 0;
		if (size % AlignNum == 0)  //所申请的内存数刚好和对齐数整除
		{
			AlignSize = size;
		}
		else
		{
			AlignSize = ((size / AlignNum + 1) * AlignNum);  //对齐 假设size=7 alignNum=8,这里就是返回8
		}
		return AlignSize;
	}
	static inline size_t RoundUp(size_t size) //对齐函数
	{
		if (size <= 128)
		{
			return _RoundUp(size, 8);
		}
		else if (size <= 1024)
		{
			return _RoundUp(size, 16);
		}
		else if (size <= 8 * 1024)
		{
			return _RoundUp(size, 128);
		}
		else if (size <= 64 * 1024)
		{
			return _RoundUp(size, 1024);
		}
		else if (size <= 256 * 1024)
		{
			return _RoundUp(size, 8 * 1024);
		}
		else
		{
			std::cout << "申请的内存数非法" << std::endl;
			assert(false);
		}
	}

	static inline size_t _Index(size_t bytes, size_t align_shift)
	{
		return ((bytes + (1 << align_shift) - 1) >> align_shift) - 1;
	}
	//计算映射的哪一个自由链表桶中
      size_t Index(size_t bytes)
	{
		assert(bytes <= MAX_BYTES);
		static int group_array[4] = { 16, 56, 56, 56 };
		if (bytes <= 128)
		{
			return _Index(bytes, 3);
		}
		else if (bytes <= 1024)
		{
			return _Index(bytes - 128, 4) + group_array[0];
		}
		else if (bytes <= 8 * 1024)
		{
			return _Index(bytes - 1024, 7) + group_array[0] + group_array[1];
		}
		else if (bytes <= 64 * 1024)
		{
			return _Index(bytes - 8 * 1024, 10) + group_array[0] + group_array[1] + group_array[2];
		}
		else if (bytes <= 256 * 1024)
		{
			return _Index(bytes - 64 * 1024, 13) + group_array[0] + group_array[1] + group_array[2] + group_array[3];
		}
		else
		{
			assert(false);
			return -1;
		}
	}



};
  

持续更新~

创作不易,点赞支持一下~
请添加图片描述

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

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

相关文章

闭包及底层原理

1.闭包概念 定义&#xff1a;能够访问到其他函数作用域中的对象的函数&#xff0c;称为闭包 误区&#xff1a;闭包不是函数里面嵌套函数 2.闭包的两种写法 2.1函数嵌套写法 // 闭包写法1: 内部嵌套函数function fn(){var a 1;function fn2(){console.log(a1);}fn2();}fn()…

在线兴趣教学类线上学习APP应用开发部署程序组建研发团队需要准备什么?

哈哈哈&#xff0c;同学们&#xff0c;我又来了&#xff0c;这个问题最近问的人有点多&#xff0c;但是说实话我也不知道&#xff0c;但是我还是总结了一下&#xff0c;毕竟我懂点代码的皮毛&#xff0c;同时我检索内容的时候&#xff0c;都是一些没有很新鲜的文案&#xff0c;…

Vue中调用组件使用kebab-case(短横线)命名法和使用大驼峰的区别

文章目录 Vue中调用组件使用kebab-case&#xff08;短横线&#xff09;命名法和使用大驼峰的区别1.解析官网手册说明2.什么是“字符串模版”&#xff0c;什么是“dom模版” Vue中调用组件使用kebab-case&#xff08;短横线&#xff09;命名法和使用大驼峰的区别 1.解析官网手册…

SSM - Springboot - MyBatis-Plus 全栈体系(二十五)

第五章 SSM 三、《任务列表案例》前端程序搭建和运行 1. 整合案例介绍和接口分析 1.1 案例功能预览 1.2 接口分析 1.2.1 学习计划分页查询 /* 需求说明查询全部数据页数据 请求urischedule/{pageSize}/{currentPage} 请求方式get 响应的json{"code":200,"f…

git pull and git fetch 到底有什么区别?

大家好这里是tony4geek 。 今天给大家介绍git pull and git fetch 有什么区别&#xff1f; 开发过程中大家肯定很多人都用到过git。获取代码有很多的git命令&#xff0c;最长用的命令是pull和fetch。那么问题来了他们之间到底有什么区别&#xff0c;该怎么使用呢&#xff1f;…

C语言之文件操作篇(2)

目录 文件状态指针 文件流 文件的顺序读写 fgetc fputc fgets fputs fscanf fprintf fread fwrite 今天接下来我们讲解文件读写函数。&#x1f197;&#x1f197;&#x1f197; 文件状态指针 文件状态指针也就是文件指示器。&#xff08;可以理解为光标&#xff09…

【U-Boot笔记整理】U-Boot 完全分析与移植

1. 大纲 大概内容如下&#xff1a; u-boot功能概述 目的功能细分 u-boot源码结构u-boot的配置、编译、连接过程 Makefile深入练习分析u-boot的Makefileu-boot可执行程序的组成 u-boot源码分析 SPL与第1阶段第2阶段核心&#xff1a;命令让u-boot的使用更加便利&#xff1a;env…

python图像检索系统设计与实现 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python图像检索系统设计与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&#xff0c…

拼多多历史价格数据接口,拼多多商品历史价格接口,拼多多API接口

采集拼多多商品历史价格接口可以采用以下方式&#xff1a; 使用价格监控工具。价格监控工具是一种可以自动监测商品价格变化的工具&#xff0c;它可以帮助消费者快速采集拼多多商品价格信息&#xff0c;还可以提供价格变动趋势的图表分析&#xff0c;使消费者更好地掌握商品价…

Apache_Log4j2查找功能JNDI注入_CVE-2021-44228

Apache_Log4j2查找功能JNDI注入_CVE-2021-44228 文章目录 Apache_Log4j2查找功能JNDI注入_CVE-2021-442281 在线漏洞解读:2 环境搭建3 影响版本&#xff1a;4 漏洞复现4.1 访问页面4.2 poc漏洞验证 4.3 在dnslog获取个域名4.4 使用bp抓包进行分析4.5 通信成功&#xff0c;此处可…

【TA 挖坑04】薄膜干涉 镭射材质 matcap

镭射材质&#xff0c;相对物理的实现&#xff1f; 万物皆可镭射&#xff0c;个性吸睛的材质渲染技术 - 知乎 (zhihu.com) 薄膜干涉材质&#xff0c;matcap更trick的方法&#xff1f;matcapremap&#xff0c; MatCap原理介绍及应用 - 知乎 (zhihu.com) 庄懂的某节课也做了mat…

红队打靶:Nyx: 1打靶思路详解(vulnhub)

目录 写在开头 第一步&#xff1a;主机发现和端口扫描 第二步&#xff1a;ssh私钥登录获取初始立足点 第三步&#xff1a;sudo gcc提权 番外篇&#xff1a;如何掉进web渗透的陷阱无法自拔 总结与思考 写在开头 我个人的打靶顺序是根据红队笔记大佬的视频顺序&#xff0…

最新最全Jmeter+InfluxDB1.8+Grafana可视化性能监控平台搭建(win11本地)

本文前置条件&#xff1a; 1.Jmeter自行部署好&#xff0c;且版本最好要5.4以上&#xff1b; 2.目前InfluxDB最新是V2版本&#xff0c;但与Grafana兼容不太好&#xff0c;且和V1版本的配置连接不一样&#xff0c;本文是InfluxDB1.8版本&#xff1b; 3.介绍的是WIN11本地部署…

《PyTorch深度学习实践》第二讲 线性模型 课后练习

《PyTorch深度学习实践》第二讲 线性模型 课后练习 问题描述代码实现实现效果 问题描述 代码实现 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D# 假设函数为 y 2x 1 x_data [1.0, 2.0, 3.0] y_data [3.0, 5.0, 7.0]# 定义…

【100天精通Python】Day70:Python可视化_绘制不同类型的雷达图,示例+代码

目录 1. 基本雷达图 2. 多组数据的雷达图 3 交互式雷达地图 4 动态雷达图 0 雷达图概述 雷达图&#xff08;Radar Chart&#xff09;&#xff0c;也被称为蜘蛛图&#xff08;Spider Chart&#xff09;或星型图&#xff0c;是一种用于可视化多维数据的图表类型。雷达图通常由…

目标文件格式

目标文件里有什么 目标文件格式 目标文件就是源代码编译后但未进行链接的中间文件&#xff08;linux下的.o&#xff09;。 ELF文件&#xff1a;从广义上看&#xff0c;目标文件与可执行文件的格式其实几乎是一样的&#xff0c;可以将目标文件与可执行文件看成是一种类型的文…

【Vue面试题二十】、你有写过自定义指令吗?自定义指令的应用场景有哪些?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;你有写过自定义指令吗&a…

相似性搜索:第 1 部分- kNN 和倒置文件索引

图片来源&#xff1a;维亚切斯拉夫叶菲莫夫 一、说明 SImilarity 搜索是一个问题&#xff0c;给定一个查询的目标是在所有数据库文档中找到与其最相似的文档。 在数据科学中&#xff0c;相似性搜索经常出现在NLP领域&#xff0c;搜索引擎或推荐系统中&#xff0c;其中需要检索最…

课题学习(七)----粘滑运动的动态算法

一、 粘滑运动的动态算法 在实际钻井过程中&#xff0c;钻柱会出现扭振和粘滑现象&#xff08;粘滑运动–B站视频连接&#xff09;&#xff0c;但并不总是呈现均匀旋转。如下图所示&#xff0c;提取一段地下数据时&#xff0c;转盘转速保持在100 r/min&#xff0c;钻头转速在0-…

Namomo Summer Camp 23 Day 1

Namomo Summer Camp 23 Day 1 - Virtual Judge B - Brexiting and Brentering AC代码: #include<bits/stdc.h> #define endl \n //#define int long long using namespace std; string s; void solve() {cin>>s;int x-1;for(int is.size()-1;i>0;i--){if(s[i…