内存池

Posted zhiminzeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存池相关的知识,希望对你有一定的参考价值。

一、内存池的概念和实现原理

内存池要解决的问题:

(1)减少malloc的次数,意味着减少对内存的浪费(主要问题)

(2)减少malloc的次数,会有一些速度和效率上的提升,但是提升不明显(顺带)

实现原理:

(1)用malloc申请一大块内存,当要分配的时候,从这一大块内存中一点一点分配,

当这一大块内存分配的差不多的时候,在申请一大块内存,然后再一点一点分配。

(因为每次malloc的时候,还会分配一些debug,尾信息,等一些附加信息的内存

所以malloc次数少了,就可以避免每次malloc带来的一些附加分配的内存空间)

二、代码示例

class A 
{
public:
    static int m_iCount;    // 每new一次记录一次
    static int m_iMallocCount;   // 每malloc一次记录一次
    // malloc 一块大的内存 可以new多次

    static void* operator new(size_t size);  // size分配的内存大小
    static void operator delete(void* pa);private:
    A * pNext;   // 指向下一个
    static A* m_FreePos;  // 总是指向一块可以分配出去的内存的首地址
    static int m_sTrunkCount;  // 一次分配多少倍的该类内存
};

int A::m_iCount = 0;
int A::m_iMallocCount = 0;

A* A::m_FreePos = nullptr;
int A::m_sTrunkCount = 50;  // 一次分配5倍的该类内存作为内存池大小,一般分配几十,根据具体情况而定

void* A::operator new(size_t size)  // 这个size是系统根据类的大小指定的
{
    //A* pa = (A*)malloc(size);
    //return pa;
    A* pTemp;
    if (m_FreePos == nullptr)
    {
        // 为空,我需要申请一大块内存
        size_t realsize = m_sTrunkCount * size;
        m_FreePos = reinterpret_cast<A*>(new char[realsize]);  // reinterpret_cast 无条件转
        // 此处的new是传统的new(不是我们自己定义的new)该出调用的是底层的malloc
        pTemp = m_FreePos;

        // 把分配的这一大块内存(5小块)彼此之间链接起来,供后续使用
// 用链表的方式来管理内存池的内存
for (; pTemp != &m_FreePos[m_sTrunkCount - 1]; ++pTemp) { pTemp->pNext = pTemp + 1; } pTemp->pNext = nullptr; // 最后一个 ++m_iMallocCount; } pTemp = m_FreePos; m_FreePos = m_FreePos->pNext; ++m_iCount; return pTemp; // new第二块新内存的时候,第一块内存的最后一个元素,还是指向第二块内存的起始地址m_FreePos // 这个关系式在new第一块内存的时候建立的链接关系 } void A::operator delete(void* pa) { //free(pa); (static_cast<A*>(pa))->pNext = m_FreePos; // 将需要释放的这块内存作为下一个将要被释放的内存,则m_FreePos变成了下两个将被释放的内存 // 因为释放的顺序是随机的 m_FreePos = static_cast<A*>(pa); // 回收内存的时候,是回收在内存池中,而不是回收到系统中 // 回收到内存池中,被内存池控制,所以不会有内存泄漏 }void fun(){ clock_t start, end; start = clock(); for (int i = 0; i < 5000000; ++i) { A* pa = new A(); } end = clock(); cout << "new 次数:" << A::m_iCount << " Malloc 次数:" << A::m_iMallocCount << " 耗时:" << end - start << endl; }

 

以上是关于内存池的主要内容,如果未能解决你的问题,请参考以下文章

newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段

C 中的共享内存代码片段

固定内存块尺寸的内存池原理及代码

nginx源代码分析之内存池实现原理

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

实现高并发内存池