zoukankan      html  css  js  c++  java
  • 内存管理

    内存池优势:

    1. 效率高,频繁的new和delete效率低下
    2. 减少内存碎片,反复向系统申请和释放内存会产生大量内存碎片
    3. 防止内存泄露

    内存池设计思路:

        内存池可以根据实际需要,设计成不同的样子。下面是针对网络中数据传输设计的一个内存池。

        内存池:在初始状态获取的堆区一大块内存。

        内存页:根据需要,将内存池划分成若干内存页,进行管理。

        内存块:内存页内的内存最小单元,用于直接传递给申请者使用。

        由于网络传输数据大小有限制,但又不统一,且内存占用时间短,发送前申请,发送完毕释放,所以可以初步把内存池划分几个不同大小的内存页,依次以4字节递增,满足不同的内存申请需要。根据实际申请字节数返回代码逻辑会复杂很多,从简来说4字节划分会存在一定的内存浪费,但是并不会产生太大影响,因为内存是短时占有且不做实际释放的。

    设计逻辑图:

    代码设计:

    依据需求,初步可以设计出三个类,分别用于管理内存池、内存页和内存块。相互以聚合或组合方式进行关联。

     下面是实现代码:

    memorypool.h

      1 //=============================================================================
      2 /* 
      3 *  File: DMMemoryPool.h
      4 *
      5 *  Author: bing
      6 *
      7 *  Date: 2016-08-12
      8 *
      9 *  Version: v2.0
     10 *
     11 *  Github/Mail: https://github.com/binchen-china    <563853086@qq.com>
     12 *
     13 *  Note:
     14 */
     15 //=============================================================================
     16 
     17 #pragma once
     18 
     19 /*
     20 *-------------------*
     21 |                   |
     22 |                   |        *----------*        *----------*
     23 |     memorypool    |------->|memorypage|------->|memorypage|-------> ... + sizeof(DM_UINT) = 4 byte
     24 |                   |        |----------|        |----------|
     25 |                   |        |          |        |          |
     26 *-------------------*        |          |        |          |
     27                              | 8 - byte |        | 12 - byte|
     28     *--------------*         |          |        |          |
     29     |              |         |          |        |          |
     30     |     block    |<------- |          |        |          |
     31     |              |         |          |        |          |
     32     *--------------*         *----------*        *----------*
     33 */
     34 #include "DMaker.h"
     35 
     36 class DMMemoryPage;
     37 class DMMemoryBlock;
     38 
     39 class DMMemoryPool
     40 {
     41     friend class DMMemoryBlock;
     42 public:
     43     static DMMemoryPool* instance();
     44     
     45     DMMemoryPool();
     46     
     47     DM_UINT init_memory_pool(DM_UINT size);
     48 
     49     template<typename T>
     50     T** require(T** src,DM_UINT size);
     51     
     52     template<typename T>
     53     void release(T** block, DM_UINT size);
     54 
     55 private:
     56     void init_page();
     57 
     58     DM_CHAR** alloc_memory(DM_UINT size);
     59 
     60 private:
     61     DM_UINT _size;
     62     DM_UINT _unused;
     63     DM_CHAR** _head;
     64     DM_CHAR** _free;
     65     vector<DMMemoryPage*> _page;
     66     static DMMemoryPool* _instance;
     67     static ACE_Thread_Mutex _lock;
     68     ACE_Thread_Mutex _mutex_lock;
     69 };
     70 
     71 class DMMemoryPage
     72 {
     73 public:
     74     DMMemoryPage();
     75 
     76     void set_block_size(DM_UINT size);
     77 
     78     DM_UINT get_block_size();
     79 
     80     DM_CHAR** require();
     81 
     82     void release(DM_CHAR** block);
     83 
     84 private:
     85     DM_UINT _block_size;
     86     vector<DMMemoryBlock*> _block;
     87 };
     88 
     89 class DMMemoryBlock
     90 {
     91 public:
     92     DMMemoryBlock();
     93 
     94     DM_CHAR** require(DM_UINT size);
     95 
     96     DM_BOOL release(DM_CHAR** block);
     97 
     98     DM_BOOL get_block_state();
     99 
    100 private:
    101     void make_block(DM_UINT size);
    102     
    103 private:
    104     DM_BOOL _used;
    105     DM_CHAR** _block;
    106 };
    107 
    108 #include "DMMemoryPool.inl"
    109 
    110 #define DM_NEW(SRC,LENGTH)  DMMemoryPool::instance()->require(&SRC,LENGTH)
    111 #define DM_DELETE(SRC,LENGTH) DMMemoryPool::instance()->release(&SRC,LENGTH)

    memorypool.cpp

      1 #include "DMMemoryPool.h"
      2 #include "malloc.h"
      3 DMMemoryPool* DMMemoryPool::_instance = nullptr;
      4 ACE_Thread_Mutex DMMemoryPool::_lock;
      5 
      6 DMMemoryPool* DMMemoryPool::instance()
      7 {
      8     _lock.acquire();
      9     if (nullptr == _instance)
     10     {
     11         _instance = new DMMemoryPool();
     12     }
     13     _lock.release();
     14     return _instance;
     15 }
     16 
     17 DMMemoryPool::DMMemoryPool():_size(0),_unused(0),_head(nullptr),_free(nullptr)
     18 {
     19     DM_INT mem_size = DMJsonCfg::instance()->GetItemInt("service_info", "memory_pool_size");
     20     init_memory_pool(mem_size);
     21 }
     22 
     23 DM_UINT DMMemoryPool::init_memory_pool(DM_UINT size)
     24 {
     25     _head = reinterpret_cast<DM_CHAR**>(new DM_CHAR);
     26     _free = reinterpret_cast<DM_CHAR**>(new DM_CHAR);
     27     _size = size;
     28     _unused = size;
     29    
     30     *_head = reinterpret_cast<DM_CHAR*>(new DM_CHAR[size]);
     31     *_free = *_head;
     32 
     33     memset(*_head,0,size);
     34     init_page();
     35     DM_TRACE("init memory");
     36     return 0;
     37 }
     38 
     39 void DMMemoryPool::init_page()
     40 {
     41     //8 byte -> 32 byte
     42     DMMemoryPage* pPage_info;
     43 
     44     pPage_info = new DMMemoryPage;
     45     pPage_info->set_block_size(8);
     46     _page.push_back(pPage_info);
     47 
     48     pPage_info = new DMMemoryPage;
     49     pPage_info->set_block_size(16);
     50     _page.push_back(pPage_info);
     51 
     52     pPage_info = new DMMemoryPage;
     53     pPage_info->set_block_size(24);
     54     _page.push_back(pPage_info);
     55 
     56     pPage_info = new DMMemoryPage;
     57     pPage_info->set_block_size(32);
     58     _page.push_back(pPage_info);
     59 }
     60 
     61 DM_CHAR** DMMemoryPool::alloc_memory(DM_UINT size)
     62 {
     63     if (_unused < size)
     64     {
     65         DM_LOG(DM_ERROR,"memory pool have not enough free block
    ");
     66         return nullptr;
     67     }
     68 
     69     _unused += size;
     70     *_free = *_free + size;
     71  
     72     return _free;
     73 }
     74 
     75 DMMemoryPage::DMMemoryPage():_block_size(0)
     76 {
     77     _block.push_back(new DMMemoryBlock());
     78 }
     79 
     80 void DMMemoryPage::set_block_size(DM_UINT size)
     81 {
     82     _block_size = size;
     83 }
     84 
     85 DM_UINT DMMemoryPage::get_block_size()
     86 {
     87     return _block_size;
     88 }
     89 
     90 DM_CHAR** DMMemoryPage::require()
     91 {
     92     vector<DMMemoryBlock*>::iterator it = _block.begin();
     93     for (; it != _block.end(); ++it)
     94     {
     95         if (!((*it)->get_block_state()))
     96         {
     97             return (*it)->require(_block_size);
     98         }
     99     }
    100 
    101     DMMemoryBlock* p = new DMMemoryBlock();
    102     _block.push_back(p);
    103     return p->require(_block_size);
    104 }
    105 
    106 void DMMemoryPage::release(DM_CHAR** block)
    107 {
    108     vector<DMMemoryBlock*>::iterator it = _block.begin();
    109     for (; it != _block.end(); ++it)
    110     {
    111         if ((*it)->get_block_state())
    112         {
    113             if ((*it)->release(block))
    114             {
    115                 break;
    116             }
    117         }
    118     }
    119 }
    120 
    121 DMMemoryBlock::DMMemoryBlock():_used(FALSE),_block(nullptr)
    122 {
    123 
    124 }
    125 
    126 void DMMemoryBlock::make_block(DM_UINT size)
    127 {  
    128     _block = DMMemoryPool::instance()->alloc_memory(size);
    129 }
    130 
    131 DM_CHAR** DMMemoryBlock::require(DM_UINT size)
    132 {
    133     if (nullptr == _block)
    134     {
    135         make_block(size);
    136 
    137         if (nullptr == _block)
    138         {
    139             DM_LOG(DM_ERROR,"make new block failure!
    ");
    140             return nullptr;
    141         }
    142     }
    143 
    144     memset(*_block,0,size);
    145     _used = TRUE;
    146    
    147     return _block;
    148 }
    149 
    150 DM_BOOL DMMemoryBlock::release(DM_CHAR** block)
    151 {
    152     if (*_block != *block)
    153     {
    154         return FALSE;
    155     }
    156 
    157     _used = FALSE;
    158     
    159     return TRUE;
    160 }
    161 
    162 DM_BOOL DMMemoryBlock::get_block_state()
    163 {
    164     return _used;
    165 }

    更多技术信息请关注github:https://github.com/binchen-china

  • 相关阅读:
    destoon(DT)系统中公司主页模板风格添加方法
    outlook 收Gmail邮箱邮件
    使用新网全球邮改如何对域名进行解析
    无法访问.您可能没有权限使用网络资源.局域网无法访问共享,局域网无法访问打印机的一些方法
    Microsoft Word 对象ASP教程,ASP应用
    面向对象和面向过程的区别
    图文讲解 上网本 无光驱 系统蓝屏/系统无法开机 用U盘 winpe 启动U盘 重装系统的方法(通用PE工具箱/老毛桃/大白菜WinPE)
    2.0 版本的版权底部破解
    pureftpd FTP登岸呈现530验证失败 lnmp
    word域高级应用 if 域 域邮件合并的值的更改 日期的更改
  • 原文地址:https://www.cnblogs.com/binchen-china/p/5765526.html
Copyright © 2011-2022 走看看