精华内容
下载资源
问答
  • 内存池优点小记

    2019-10-03 02:41:10
    所谓池, 其实就是一种资源的集中, 那么内存池, 自然就是预先将内存集中在一块. 内存池帮助我们解决的问题: 增加动态申请的效率 减少陷入内核的次数 减少系统内存碎片 提升内存使用率 转载于:...

    所谓池, 其实就是一种资源的集中, 那么内存池, 自然就是预先将内存集中在一块.

    内存池帮助我们解决的问题:

    1. 增加动态申请的效率
    2. 减少陷入内核的次数
    3. 减少系统内存碎片
    4. 提升内存使用率

    转载于:https://www.cnblogs.com/Smart_Joe/archive/2012/05/05/2484817.html

    展开全文
  • 内存池

    2018-08-08 23:55:12
    内存池优点是可以有效的减少内存碎片化,分配内存更加快速,减少内存泄漏等优点。    内存池是在真正使用内存之前,先申请分配一个大的内存块留作备用。当真正需要使用内存的时候,就从内存池中分配一...

    内存池概念

       通常我们用new和malloc来分配内存的话,由于申请的大小不确定,所以频繁的使用时会带来内存碎片和效率降低的问题。为了克服这种问题提出了内存池的概念。内存池是一种内存分配方式。内存池的优点是可以有效的减少内存碎片化,分配内存更加快速,减少内存泄漏等优点。
       内存池是在真正使用内存之前,先申请分配一个大的内存块留作备用。当真正需要使用内存的时候,就从内存池中分配一块内存使用,当这块内存用完后再还给内存池。若内存块不够就再申请一块大的内存块。

    可以看出这样做有两个好处:

    1. 由于向内存申请的内存块都比较大,所以能够降低外碎片的问题。
    2. 一次性向系统内存申请一块大的内存慢慢用,避免了频繁向系统内存请求内存操作,提高内存分配的效率。

    内存碎片化
    设计方法

    展开全文
  •  采用内存池,需要内存时候,向内存池拿,使用完后就进行释放。     固定内存 内存池 优点 1 实现简单 2 直接使用,效率高 1 适合任何场景 缺点 1 受到应用场景限制 1 需要管理...
    
    

     采用固定内存就是在服务启动的时候,分配固定大小的内存,在处理请求的时候,直接在这片内存上操作

            采用内存池,需要内存时候,向内存池拿,使用完后就进行释放。


            

      固定内存 内存池
    优点 1 实现简单
    2 直接使用,效率高
    1 适合任何场景
    缺点 1 受到应用场景限制 1 需要管理内存池

    展开全文
  • C++ 内存池介绍与经典内存池的实现

    万次阅读 多人点赞 2015-11-01 00:04:38
    1.默认内存管理函数的不足利用默认的内存管理函数new/delete或malloc/free在堆上分配和释放内存会有一些额外的开销。系统在接收到分配一定大小内存的请求时,首先查找内部维护的内存空闲块表,并且需要根据一定的...

    代码编译运行环境:VS2012+Debug+Win32


    1.默认内存管理函数的不足

    利用默认的内存管理操作符new/delete和函数malloc()/free()在堆上分配和释放内存会有一些额外的开销。

    系统在接收到分配一定大小内存的请求时,首先查找内部维护的内存空闲块表,并且需要根据一定的算法(例如分配最先找到的不小于申请大小的内存块给请求者,或者分配最适于申请大小的内存块,或者分配最大空闲的内存块等)找到合适大小的空闲内存块。如果该空闲内存块过大,还需要切割成已分配的部分和较小的空闲块。然后系统更新内存空闲块表,完成一次内存分配。类似地,在释放内存时,系统把释放的内存块重新加入到空闲内存块表中。如果有可能的话,可以把相邻的空闲块合并成较大的空闲块。默认的内存管理函数还考虑到多线程的应用,需要在每次分配和释放内存时加锁,同样增加了开销。

    可见,如果应用程序频繁地在堆上分配和释放内存,会导致性能的损失。并且会使系统中出现大量的内存碎片,降低内存的利用率。默认的分配和释放内存算法自然也考虑了性能,然而这些内存管理算法的通用版本为了应付更复杂、更广泛的情况,需要做更多的额外工作。而对于某一个具体的应用程序来说,适合自身特定的内存分配释放模式的自定义内存池可以获得更好的性能。

    2.内存池简介

    2.1 内存池的定义

    内存池(Memory Pool)是一种内存分配方式。通常我们习惯直接使用new、malloc等API申请内存,这样做的缺点在于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。

    2.2 内存池的优点

    内存池则是在真正使用内存之前,预先申请分配一定数量、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。这样做的一个显著优点是,使得内存分配效率得到提升。

    2.3 内存池的分类

    应用程序自定义的内存池根据不同的适用场景又有不同的类型。从线程安全的角度来分,内存池可以分为单线程内存池和多线程内存池。单线程内存池整个生命周期只被一个线程使用,因而不需要考虑互斥访问的问题;多线程内存池有可能被多个线程共享,因此需要在每次分配和释放内存时加锁。相对而言,单线程内存池性能更高,而多线程内存池适用范围更加广泛。

    从内存池可分配内存单元大小来分,可以分为固定内存池和可变内存池。所谓固定内存池是指应用程序每次从内存池中分配出来的内存单元大小事先已经确定,是固定不变的;而可变内存池则每次分配的内存单元大小可以按需变化,应用范围更广,而性能比固定内存池要低。

    3.经典的内存池技术

    内存池技术因为其对内存管理有着显著的优点,在各大项目中广泛应用,备受推崇。但是,通用的内存管理机制要考虑很多复杂的具体情况,如多线程安全等,难以对算法做有效的优化,所以,在一些特殊场合,实现特定应用环境的内存池在一定程度上能够提高内存管理的效率。

    经典内存池技术,是一种用于分配大量大小相同的小对象的技术。通过该技术可以极大加快内存分配/释放过程。既然是针对特定对象的内存池,所以内存池一般设置为类模板,根据不同的对象来进行实例化。

    3.1 经典内存池的设计

    3.1.1 经典内存池实现过程

    (1)先申请一块连续的内存空间,该段内存空间能够容纳一定数量的对象;
    (2)每个对象连同一个指向下一个对象的指针一起构成一个内存节点(Memory Node)。各个空闲的内存节点通过指针形成一个链表,链表的每一个内存节点都是一块可供分配的内存空间;
    (3)某个内存节点一旦分配出去,从空闲内存节点链表中去除;
    (4)一旦释放了某个内存节点的空间,又将该节点重新加入空闲内存节点链表;
    (5)如果一个内存块的所有内存节点分配完毕,若程序继续申请新的对象空间,则会再次申请一个内存块来容纳新的对象。新申请的内存块会加入内存块链表中。

    经典内存池的实现过程大致如上面所述,其形象化的过程如下图所示:
    在这里插入图片描述

    如上图所示,申请的内存块存放三个可供分配的空闲节点。空闲节点由空闲节点链表管理,如果分配出去,将其从空闲节点链表删除,如果释放,将其重新插入到链表的头部。如果内存块中的空闲节点不够用,则重新申请内存块,申请的内存块由内存块链表来管理。

    注意,本文涉及到的内存块链表和空闲内存节点链表的插入,为了省去遍历链表查找尾节点,便于操作,新节点的插入均是插入到链表的头部,而非尾部。当然也可以插入到尾部,读者可自行实现。

    3.1.2 经典内存池数据结构设计

    按照上面的过程设计,内存池类模板有这样几个成员。

    两个指针变量:
    内存块链表头指针:pMemBlockHeader;
    空闲节点链表头指针:pFreeNodeHeader;

    空闲节点结构体:

    struct FreeNode
    {
    	FreeNode* pNext;
    	char data[ObjectSize];
    };
    

    内存块结构体:

    struct MemBlock
    {
    	MemBlock *pNext;
    	FreeNode data[NumofObjects];
    };
    

    3.2 经典内存池的实现

    根据以上经典内存池的设计,编码实现如下。

    #include <iostream>
    using namespace std;
    
    template<int ObjectSize, int NumofObjects = 20>
    class MemPool
    {
    private:
    	//空闲节点结构体
    	struct FreeNode
    	{
    		FreeNode* pNext;
    		char data[ObjectSize];
    	};
    
    	//内存块结构体
    	struct MemBlock
    	{
    		MemBlock* pNext;
    		FreeNode data[NumofObjects];
    	};
    
    	FreeNode* freeNodeHeader;
    	MemBlock* memBlockHeader;
    
    public:
    	MemPool()
    	{
    		freeNodeHeader = NULL;
    		memBlockHeader = NULL;
    	}
    
    	~MemPool()
    	{
    		MemBlock* ptr;
    		while (memBlockHeader)
    		{
    			ptr = memBlockHeader->pNext;
    			delete memBlockHeader;
    			memBlockHeader = ptr;
    		}
    	}
    	void* malloc();
    	void free(void*);
    };
    
    //分配空闲的节点
    template<int ObjectSize, int NumofObjects>
    void* MemPool<ObjectSize, NumofObjects>::malloc()
    {
    	//无空闲节点,申请新内存块
    	if (freeNodeHeader == NULL)
    	{
    		MemBlock* newBlock = new MemBlock;
    		newBlock->pNext = NULL;
    
    		freeNodeHeader=&newBlock->data[0];	 //设置内存块的第一个节点为空闲节点链表的首节点
    		//将内存块的其它节点串起来
    		for (int i = 1; i < NumofObjects; ++i)
    		{
    			newBlock->data[i - 1].pNext = &newBlock->data[i];
    		}
    		newBlock->data[NumofObjects - 1].pNext=NULL;
    
    		//首次申请内存块
    		if (memBlockHeader == NULL)
    		{
    			memBlockHeader = newBlock;
    		}
    		else
    		{
    			//将新内存块加入到内存块链表
    			newBlock->pNext = memBlockHeader;
    			memBlockHeader = newBlock;
    		}
    	}
    	//返回空节点闲链表的第一个节点
    	void* freeNode = freeNodeHeader;
    	freeNodeHeader = freeNodeHeader->pNext;
    	return freeNode;
    }
    
    //释放已经分配的节点
    template<int ObjectSize, int NumofObjects>
    void MemPool<ObjectSize, NumofObjects>::free(void* p)
    {
    	FreeNode* pNode = (FreeNode*)p;
    	pNode->pNext = freeNodeHeader;	//将释放的节点插入空闲节点头部
    	freeNodeHeader = pNode;
    }
    
    class ActualClass
    {
    	static int count;
    	int No;
    
    public:
    	ActualClass()
    	{
    		No = count;
    		count++;
    	}
    
    	void print()
    	{
    		cout << this << ": ";
    		cout << "the " << No << "th object" << endl;
    	}
    
    	void* operator new(size_t size);
    	void operator delete(void* p);
    };
    
    //定义内存池对象
    MemPool<sizeof(ActualClass), 2> mp;
    
    void* ActualClass::operator new(size_t size)
    {
    	return mp.malloc();
    }
    
    void ActualClass::operator delete(void* p)
    {
    	mp.free(p);
    }
    
    int ActualClass::count = 0;
    
    int main()
    {
    	ActualClass* p1 = new ActualClass;
    	p1->print();
    
    	ActualClass* p2 = new ActualClass;
    	p2->print();
    	delete p1;
    
    	p1 = new ActualClass;
    	p1->print();
    
    	ActualClass* p3 = new ActualClass;
    	p3->print();
    
    	delete p1;
    	delete p2;
    	delete p3;
    }
    

    程序运行结果:

    004AA214: the 0th object
    004AA21C: the 1th object
    004AA214: the 2th object
    004AB1A4: the 3th object
    

    3.3 程序分析

    阅读以上程序,应注意以下几点。
    (1)对一种特定的类对象而言,内存池中内存块的大小是固定的,内存节点的大小也是固定的。内存块在申请之初就被划分为多个内存节点,每个 Node 的大小为 ItemSize。刚开始,所有的内存节点都是空闲的,被串成链表。

    (2)成员指针变量 memBlockHeader 是用来把所有申请的内存块连接成一个内存块链表,以便通过它可以释放所有申请的内存。freeNodeHeader 变量则是把所有空闲内存节点串成一个链表。freeNodeHeader为空则表明没有可用的空闲内存节点,必须申请新的内存块。

    (3)申请空间的过程如下。在空闲内存节点链表非空的情况下,malloc 过程只是从链表中取下空闲内存节点链表的头一个节点,然后把链表头指针移动到下一个节点上去。否则,意味着需要一个新的内存块。这个过程需要申请新的内存块切割成多个内存节点,并把它们串起来,内存池技术的主要开销就在这里。

    (4)释放对象的过程就是把被释放的内存节点重新插入到内存节点链表的开头。最后被释放的节点就是下一个即将被分配的节点。

    (5)内存池技术申请/释放内存的速度很快,其内存分配过程多数情况下复杂度为 O(1),主要开销在 freeNodeHeader 为空时需要生成新的内存块。内存节点释放过程复杂度为 O(1)。

    (6) 在上面的程序中,指针 p1 和 p2 连续两次申请空间,它们代表的地址之间的差值为 8,正好为一个内存节点的大小(sizeof(FreeNode))。指针 p1 所指向的对象被释放后,再次申请空间,得到的地址与刚刚释放的地址正好相同。指针 p3 多代表的地址与前两个对象的地址相聚很远,原因是第一个内存块中的空闲内存节点已经分配完了,p3 指向的对象位于第二个内存块中。

    以上内存池方案并不完美,比如,只能单个单个申请对象空间,不能申请对象数组,内存池中内存块的个数只能增大不能减少,未考虑多线程安全等问题。现在,已经有很多改进的方案,请读者自行查阅相关资料。


    参考文献

    [1] C++ 应用程序性能优化,第 6 章:内存池
    [2] 陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008.7.8什么是内存池技术

    展开全文
  • 最近开始学习内存池技术,《高质量c++/c编程指南》在内存管理的第一句话就是:欢迎进入内存这片... 一、不定长内存池优点:不需要为不同的数据创建不同的内存池,缺点是分配出去的内存池不能回收到池中(?)。代表有a
  • 内存池的理解

    千次阅读 2017-11-14 22:24:53
    使用内存池优点有:降低动态申 请内存的次数,提升系统性能,减少内存碎片,增加内存空间使用率。 内存池的分类: 一、不定长内存池优点:不需要为不同的数据创建不同的内存池,缺点是分配出去的...
  • 进程池,线程池,内存池
  • 高并发内存池

    2019-03-07 14:21:38
    第一种内存池:简单内存池 第二种内存池:O1定长内存池 第三种内存池:哈希映射的FreeList池 第四种内存池:高并发内存池 Thread Cache Central Cache Page Cache 整个内存池的模型: 申请内存: 释放内存...
  • C++实现内存池

    万次阅读 多人点赞 2018-08-09 10:02:54
    1. 内存池设计 1.1 目的 在给定的内存buffer上建立内存管理机制,根据用户需求从该buffer上分配内存或者将已经分配的内存释放回buffer中。 1.2 要求 尽量减少内存碎片,平均效率高于C语言的malloc和free。 1.3 ...
  • 如何设计一个简单内存池

    千次阅读 2016-12-04 20:59:39
    内存池优点就是可以有效的减少内存碎片化,分配内存更快速,减少内存泄漏等优点。  内存池是在真正使用内存之前,先申请分配一个大的内存块留作备用。当真正需要使用内存的时候,就从内存池中分配一块
  • 动态内存管理本质是对一大块内存(可以理解为数组)分配和释放的管理,lwip提供了2种动态内存管理策略内存池pool、内存堆heap 内存池memp.c/h 系统只能为用户分配几个固定大小的内存块,优点是比较快,不会产生内存...
  • 内存池系列】内存池设计与应用

    千次阅读 2012-05-12 21:46:50
    曾经看过《C++应用程序性能优化》里面的内存池结构,也看过ACE自己的自增式内存池结构,感觉每个都有自己的优点。但是大体思路都是一致的,那就是一次new出一大块内存,然后按照2的幂分配内存块。当申请的内存不够的...
  • Arena内存池简介

    2020-11-25 18:09:31
    什么是内存池内存池(Memory Pool)是一种内存分配方式,又被称为固定大小区块规划(fixed-size-blocks allocation)。 通常我们习惯直接使用new、malloc等API申请分配内存,这样做的缺点在于:由于所申请内存块...
  • stl内存池学习

    千次阅读 2015-09-04 16:47:06
    最近开始学习内存池技术,《高质量c++/c编程指南》在内存管理的第一句话就是:欢迎进入内存这片... 一、不定长内存池优点:不需要为不同的数据创建不同的内存池,缺点是分配出去的内存池不能回收到池中(?)。代表有a
  • 内存池?进程池?线程池?

    千次阅读 2013-10-05 22:45:44
    内存池 平常我们使用new、malloc在堆区申请一块内存,但由于每次申请的内存大小不一样就会产生很多内存碎片,造成不好管理与浪费的情况 内存池则是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下...
  • 1 定长分块的内存池: 每次申请的内存量是常数。例如每次只能申请128字节,不多不少。 参考Scott Meyers effective C++定长分块的内存池。 这种内存池结构简单,易于实现和理解,效率也出奇的高...
  • 内存池总结

    千次阅读 2012-05-23 19:11:43
    为什么要内存池? (1) 在调试阶段检查内存泄露。C++的指针给大家带来了很大的方便,但是它对内存的自由操作也带来了内存泄露等一系列问题,在一些嵌入式软件开发过程中 (2) 减少内存碎片。频繁的从堆中...
  • 内存池技术

    千次阅读 2019-06-02 13:54:21
    一、 自定义内存池性能优化的原理 在编程实践中,不可避免地要大量用到堆上的内存。例如在程序中维护一个链表的数据结构时,每次新增或者删除一个链表的节点,都需要从内存堆上分配或者释放一定的内存;在维护一个...
  • Boost Pool 库提供了一个内存池分配器,它是一个...使用pool内存池主要有以下两个优点: (1) 能够有效地管理许多小型对象的分配和释放工作,避免了自己去管理内存而产生的内存碎片和效率低下问题。 (2)告别...
  • 内存池的实现

    2015-05-11 23:24:29
    1.内存池要解决什么问题? 直接用malloc/free进行内存的申请和释放,有一些弊端,比如开销比较大,在申请的时候会根据最优匹配算法找到一个空闲的内存,在释放的时候可能需要合并空闲的内存块,这些都设计到开销;第...
  • NGINX 内存池

    2014-06-07 10:44:55
    内存池有众多的好处,比如减少外部碎片,加快分配速度等。 NGINX
  • C++ 内存管理----内存池

    千次阅读 2015-03-21 16:04:44
    C++ 内存管理技术,以及 内存池的实现。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 79,341
精华内容 31,736
关键字:

内存池优点