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

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;
		}
	}



};
  

持续更新~

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

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值