0
点赞
收藏
分享

微信扫一扫

项目--高并发内存池

青鸾惊鸿 2022-02-13 阅读 88

学习C++也有不少时日了,今天我们来学习一个项目,该项目是借鉴谷歌的tc-malloc,让我们一起来认识一下这个设计极其优秀的项目吧

需求分析

我们该项目利用了设计模式中的池化技术,在传统的内存池上进行了优化,该内存池可以有效地提高内存申请效率以及解决内存碎片化的问题

普通内存池的优缺点

我们先来回顾一下内存池的主要思路,就是预先开辟一大块内存,当我们程序需要使用内存时,直接从该大块内存中拿取一块,可以提高申请释放效率,而不需要再去new/malloc从堆中申请内存

优点:提高效率,解决部分内存碎片问题

缺点:无法处理高并发时申请内存存在的锁竞争问题,该问题会使效率降低

我们的内存池解决的问题就是上面这些问题

主要设计思路

高并发内存池整体框架由以下三部分组成,各部分的功能如下:

那么我们就从0开始对这个项目进行实现吧

thread cache线程缓存

首先,我们思考一下,我们的这个内存池最主要的目的是什么?就是可以同时分配内存给不同的线程,基于这一点,参考我们内存池的设计,我们设计了一个成员是自由双向链表的哈希桶作为thread_cache的主要结构

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bmzICDnlJ8=,size_20,color_FFFFFF,t_70,g_se,x_16 

private:FreeList _freeLists[NFREELISTS];//自由链表大小为NFREELISTS

那么我们就需要对双向链表进行基础实现

FreeList类

我们既然是挂在哈希桶上,要用这个链表来对内存块进行存储,所以我们结点需要1.头结点指针。2.哈希桶下结点个数。

private:void* _head = nullptr;size_t _size = 0;

我们想到,当我们一个线程需要内存时,我们将对应大小的内存返回给线程,所以我们诞生了

// 头删void* Pop()//将一份内存返回给线程{void* obj = _head;_head = NextObj(_head);_size -= 1;return obj;}

我们在这里需要对NextObj(_head)进行说明,这个函数其实是代替链表的next而生的,下面是他的具体实现

inline void*& NextObj(void* obj)//obj的下一个结点{return *((void**)obj);//我们将obj的前4/8个字节用以存储下一个节点的地址,返回obj的前4/8个字节//相当于返回了下一个结点,这里我们采用对void**解引用,就是因为使用void**才真正提取出了一块内存对//象随着32位/64位机器的不同取出前4/8个字节(解void**就是看void*的大小,而void*的大小在32位下就是4,64位就是8),注:void*一般而言是不能解引用的(Linux下可以),但是void**可以}

有了将内存传给线程,那么就会有线程将用完的内存还给内存池,随意我们的链表还有插入操作

// 头插void Push(void* obj){NextObj(obj) = _head;_head = obj;_size += 1;}

以及一些基本的函数

bool Empty(){return _head == nullptr;}size_t MaxSize(){return _max_size;}void SetMaxSize(size_t n){_max_size = n;}size_t Size(){return _size;}

 

 

 

 

 

 

 

 


 

 

 

举报

相关推荐

0 条评论