By - admin

内存池设计和原理 – yuanchunsi的博客

1. 内存池设计

决意

在事先安排的内存特大的上创办内存监督机制,粉底用户恳求从该buffer上分派内存或许将曾经分派的内存代班人回buffer中。

索赔

极力贬低的价值内存段,在C边境居民的特殊风习中,公正地效能高于malloc和free。。

设计思绪

把特大的陷于四分配,居于首位地分配是mem_池构造;第2分配是内存测绘表;第3分配是内存块构造buffe;第4分配是现实可分派内存。完整特大的构造如图1所示。:

图1 内存特大的构造图

图1 内存特大的构造图

第1分配的决意是经过mem_p把持完整内存池。。

第2分配的效能是记载第4分配,换句话说,可分派内存区域的现实运用境况。表正中鹄的每个小牢房表现独立通过作弊预先安排好最后的大部分的内存块。,多个延续块结合独立chun,每个区块的仔细构造如图2所示。:

图2 memory 方块构造图

图2 memory 方块构造图

内脏count表现该block前面的与该block同属于独立chunk的blokc的编号,Start表现块得名次的块的通行学位块锁上。真正start因此域唯一的在每个chunk的决赛独立block中才会用到(用于从通常chunk找寻前独立chunk的通行学位使就职),pmem块是独立方针,导演mem块构造。无论哪一个内存块都将排列方向为块大部分的概数倍。。

第3分配是独立内存块 pool,它的效能是存储器完整Pro可购得的的内存块构造。mem_chunk 池正中鹄的内存块被棉纸重叠向列表构造(灵活的拔出。每个mem_块的构造图如图3所示。:

图3 memory 块构造图

图3 memory 块构造图

内脏pmem_块导演内存测绘t中块的使就职,对立面代表对立面球,区分的取得对应的域粗区分。

第4分配是可以现实分派给用户的内存。

以及这四个一组之物分配,完整内存池监督,另一件要紧的事是旧事。 chunk set。怨恨每独立元素都来自于Mem ou Chun pool,但它和Mem ou Chunk紧随其后 池当中的分别位于每个池都有本人的内存 chunk中记载了通常可购得的的大量内存的互插书信。而mem_chunk 池内存 块的物质是无把握、不确定的事物的。你可以默认因此华盛顿州的大块头 pool与memory
chunk set:mem_chunk 池用于内存 chunk set分派内存池,简单地内存池每回分派通过作弊预先安排好最后的数的内存,内存块构造的大部分。内存池顺序首要搜索因此内存 chunk 设置为获取可分派内存。在memory chunk 在集中上创办区分的数据构造外形区分的内存P,这也会理由区分的搜索效能,对内存池机能的导演情绪反应,本文嗣后将引见两个内存池的取得。

内存池监督的运转一道菜

  • 设定初值:内存测绘表中唯一的一则内存书信可购得的。,大部分为的内存池正中鹄的财产可购得的内存。从memory chunk 在poo中分派内存块,使其导演内存测绘表正中鹄的居于首位地个块,并粉底详细取得装满mem块正中鹄的对立面域,与将内存块添加到内存中 chunk set中。
  • 敷内存:当用户恳求独立内存时,率先,在收回通告中 chunk 在SE中查找优美的的内存块。假定所需的内存块是foun,在内存测绘表中查找相关联的的块,修正了Chun块体构造的物质,与粉底修正后的chun修正内存 chunk 集中中块的物质,决赛,言归正传分派内存的通行学位地址。;不然言归正传空值。
  • 代班人内存:当用户代班人内存时,率先,找到与内存测绘表对应的块,与尝试将块与其毗邻的的块兼并,修正块中相关联的块的物质并修正内存 chunk 集中或内存中相关联的块的物质 chunk set添加新的内存块(当内存无法兼并时会发作这种境况。

缩减收回通告段

本文设计的办法可是在一定程度上缩减收回通告段,缺席完整避开收回通告段。详细办法列举如下:

当用户代班人内存时,尝试将此内存与其毗邻的内存兼并。假定毗邻的内存未分派,则兼并成,在Mergin后来的用作内存块;假定毗邻的内存已分派内存,则无法兼并,代班人的内存块用作独立的内存块。。

2 内存池取得连接列表构造

机能剖析

链表构造的内存池取得是指内存 chunk 集中取得为双连接列表构造。这种办法的优点和错误列举如下:

优点:灵活的代班人内存,O(1)错综复杂的情况。

错误:内存分派慢慢地,O(n)错综复杂的情况。

内存池运转情况替换图

绿色表现未运用的内存,白色表现收回通告曾经在咱们体内。每个块代表64B,此值可以粉底指定的需求设置。

图4 内存池设定初值情况

图4 内存池设定初值情况

图5 最早的敷128B内存后

图5 最早的敷128B内存后

图6 第n次消耗、代班人内存后

图6 第n次消耗、代班人内存后

图7 64B内存代班人前后

图7 64B内存代班人前后

3 内存池取得广泛的顶级堆构造

机能剖析

广泛的顶级堆构造的内存池取得是指 chunk 集中被取得为独立大的顶部堆构造。这种办法的优点和错误列举如下:

优点:缩减分派内存的时期复合物,O(log(n))。

错误:繁殖代班人内存的时期复合物,O(log(n))。

内存池运转情况替换图

绿色表现未运用的内存,白色表现收回通告曾经在咱们体内。每个块代表64B,此值可以粉底指定的需求设置。

图8 内存池设定初值情况

图8 内存池设定初值情况

图9 最早的敷128B内存后

图9 最早的敷128B内存后

图10 第n次消耗、代班人内存后

图10 第n次消耗、代班人内存后

图11 64B内存代班人前后

图11 64B内存代班人前后

4 机能测得最后

  • 测得最后靶子:C边境居民的特殊风习malloc、本文正中鹄的两个内存池(大部分为500m,现实可分派内存为310。
  • 测得最后指示:实行n=2000随机分派、代班人随机大部分存储器器的时期比(排序64b~1024b)。
  • 实验办法1:

(1) 产生物理反应n个随机数字,大部分排序从64到1024,用于表现要分派的n个内存大部分;

(2) 产生物理反应n个随机数字,取值 为0或许1,表现每回分派后条件毫不迟疑代班人内存;

(3) 测C边境居民的特殊风习malloc、本文正中鹄的两个内存池实行n次随机分派、代班人随机大部分存储器器的时期比;

(4) 反复(3)m=200次,记载每个易被说服的的比率,并折叠相关联的的侧面。

(1) 产生物理反应n个随机数字,大部分中间状态A和B当中(参赛人A=64,b=1024),用于表现要分派的n个内存大部分;

(2) 测C边境居民的特殊风习malloc、自由的内存池和本文正中鹄的两个内存池实行n个分派、代班人随机大部分存储器器的时期比;

(3) 反复(2)m=512次,每回分派的存储容量的排序比前一次大1024B,记载在每个时期点通行的比率,并折叠相关联的的侧面。

机能测得最后最后-连接列表最后内存池

图12 连接列表内存池机能测得最后最后

图12 连接列表内存池机能测得最后最后

连接列表内存池机能测得最后最后

图13 连接列表内存池机能测得最后最后

4.2 机能测得最后最后-广泛的顶级堆内存池

图14 大顶堆内存池机能测得最后最后

图14 大顶堆内存池机能测得最后最后

图15 大顶堆内存池机能测得最后最后

图15 大顶堆内存池机能测得最后最后

4.3 机能比较地

图16 两个内存池机能测得最后最后的比较地

图16 两个内存池机能测得最后最后的比较地

图17 两个内存池机能测得最后最后的比较地

图17 两个内存池机能测得最后最后的比较地

5 裁决

从下面的内存池机能测得最后最后可以看出,相形C边境居民的特殊风习malloc和free,内存池举起了分派和代班人内存的效能。,这种优势在分派更大更快的M时尤为展现。。

同时,可以看出内存池的机能,相反,链表内存池的机能在表面之下。这再次暗示O(log(n))优于O(n)是有条件的。。自然,本文正中鹄的测得最后相当极限,可能性在对立面测得最后文献的编集中,广泛的顶级堆的内存池机能。

附:源代码

连接列表构造内存池:

  1. #ifndef _MEMORYPOOL_H  
  2. #define _MEMORYPOOL_H  
  3. #include <  
  4. 界限minUnitSize 64  
  5. 界限地址疏远8  
  6. #define SIZE_ALIGN MINUNITSIZE  
  7. struct memory_chunk;  
  8. typedef struct memory_block  
  9. {  
  10.     size_t count;  
  11.     size_t start;  
  12.     memory_chunk* pmem_chunk;  
  13. }memory_block;  
  14.   
  15. typedef struct memory_chunk  
  16. {  
  17.     memory_block* pfree_mem_addr;  
  18.     memory_chunk* pre;  
  19.     memory_chunk* next;  
  20. }memory_chunk;  
  21.   
  22. typedef struct MEMORYPOOL  
  23. {  
  24.     void *memory;  
  25.     size_t size;  
  26.     memory_block* pmem_map;   
  27.     memory_chunk* pfree_mem_chunk;  
  28.     memory_chunk* pfree_mem_chunk_pool;  
  29.     size_t mem_used_size;   
  30.     size_t mem_map_pool_count;   
  31.     size_t free_mem_chunk_count;   
  32.     size_t mem_map_unit_count;   
  33.     size_t mem_block_count;   
  34. }MEMORYPOOL, *PMEMORYPOOL;  
  35.   
  36.  
  37.  
  38.  
  39.  
  40.   
  41. PMEMORYPOOL CreateMemoryPool(void* pBuf, size_t sBufSize);  
  42.   
  43.  
  44.   
  45. void ReleaseMemoryPool(PMEMORYPOOL* ppMem) ;   
  46.   
  47.  
  48.  
  49.  
  50.  
  51.   
  52. void* GetMemory(size_t sMemorySize, PMEMORYPOOL pMem) ;  
  53.   
  54.   
  55.  
  56.  
  57.  
  58.   
  59. void FreeMemory(void *ptrMemoryBlock, PMEMORYPOOL pMem) ;  
  60.   
  61. #endif //_MEMORYPOOL_H  

 

MemoryPool.cpp

  1. #include “”  
  2. #include <  
  3. #include “”  
  4.   
  5.  
  6.   
  7. size_t check_align_addr(void*& pBuf)  
  8. {  
  9.     size_t疏远=0
  10.     size_t addr = (int)pBuf;  
  11.     align = (ADDR_ALIGN – addr % ADDR_ALIGN) % ADDR_ALIGN;  
  12.     pBuf = (char*)pBuf + align;  
  13.     return align;  
  14. }  
  15.   
  16.  
  17.   
  18. size_t check_align_block(size_t量级)
  19. {  
  20.     size_t疏远=大部分百分率极小值
  21.       
  22.     return大部分-疏远
  23. }  
  24.   
  25.  
  26.   
  27. size_t check_align_size(size_t量级)
  28. {  
  29.     size = (size + SIZE_ALIGN – 1) / SIZE_ALIGN * SIZE_ALIGN;  
  30.     return size;  
  31. }  
  32.   
  33.  
  34.   
  35. memory_chunk* create_list(memory_chunk* pool, size_t计数)
  36. {  
  37.     if (!池)
  38.     {  
  39.         return NULL;  
  40.     }  
  41. 内存块*头=空
  42.     for (size_t i = 0; i < count; i++)  
  43.     {  
  44.         pool->pre = NULL;  
  45.         pool->next = head;  
  46.         if(头部!空)
  47.         {  
  48.             head->pre = pool;              
  49.         }  
  50. 头=水池
  51.         pool++;  
  52.     }  
  53.     return head;  
  54. }  
  55. memory_chunk* front_pop(memory_chunk*& 池)
  56. {  
  57.     if (!池)
  58.     {  
  59.         return NULL;  
  60.     }  
  61. memory_chunk*tmp=池
  62.     pool = tmp->next;  
  63.     pool->pre = NULL;  
  64.     return  tmp;  
  65. }  
  66. void push_back(memory_chunk*& head, memory_chunk* element)  
  67. {  
  68.     if(头部=空)
  69.     {  
  70. head=元素
  71.         head->pre = element;  
  72.         head->next = element;  
  73.         return;  
  74.     }  
  75.     head->pre->next = element;  
  76.     element->pre = head->pre;  
  77.     head->pre = element;  
  78.     element->next = head;  
  79. }  
  80. void push_front(memory_chunk*& head, memory_chunk* element)  
  81. {  
  82.     element->pre = NULL;  
  83.     element->next = head;  
  84.     if(头部!空)
  85.     {  
  86.         head->pre = element;           
  87.     }  
  88. head=元素
  89. }  
  90. void delete_chunk(memory_chunk*& head, memory_chunk* element)  
  91. {  
  92.       
  93.     if (element =空)
  94.     {  
  95.         return;  
  96.     }  
  97.       
  98.     else if(元素==头部)
  99.     {  
  100.           
  101.         if (head->pre == head)  
  102.         {  
  103. 头=空
  104.         }  
  105.         else  
  106.         {  
  107.             head = element->next;  
  108.             head->pre = element->pre;  
  109.             head->pre->next = head;  
  110.         }  
  111.     }  
  112.       
  113.     else if (element->next == head)  
  114.     {  
  115.         head->pre = element->pre;  
  116.         element->pre->next = head;  
  117.     }  
  118.     else  
  119.     {  
  120.         element->pre->next = element->next;  
  121.         element->next->pre = element->pre;  
  122.     }  
  123.     element->pre = NULL;  
  124.     element->next = NULL;  
  125. }  
  126.   
  127.  
  128.   
  129. void* index2addr(PMEMORYPOOL mem_pool, size_t锁上)
  130. {  
  131.     char* p = (char*)(mem_pool->memory);  
  132.     void* ret = (void(P 指示*分钟数)
  133.       
  134.     return ret;  
  135. }  
  136.   
  137.  
  138.   
  139. size_t addr2index(PMEMORYPOOL mem_pool, void地址)
  140. {  
  141.     char* start = (char*)(mem_pool->memory);  
  142.     char* p = (char*)addr;  
  143.     size_t index = (p – start) / MINUNITSIZE;  
  144.     return index;  
  145. }  
  146.   
  147.  
  148.  
  149.  
  150.  
  151.   
  152. PMEMORYPOOL CreateMemoryPool(void* pBuf, size_t sBufSize)  
  153. {  
  154.     memset(pBuf, 0, sBufSize);  
  155.     PMEMORYPOOL mem_pool = (PMEMORYPOOL)pBuf;  
  156.       
  157.     size_t mem_pool_struct_size = sizeof(MEMORYPOOL);  
  158.     mem_pool->mem_map_pool_count = (sBufSize – mem_pool_struct_size + MINUNITSIZE – 1) / MINUNITSIZE;  
  159.     mem_pool->mem_map_unit_count = (sBufSize – mem_pool_struct_size + MINUNITSIZE – 1) / MINUNITSIZE;  
  160.     mem_pool->pmem_map = (memory_block*)((char*)pBuf + mem_pool_struct_size);  
  161.     mem_pool->pfree_mem_chunk_pool = (memory_chunk*)((char*)pBuf + mem_pool_struct_size + sizeof(memory_block) * mem_pool->mem_map_unit_count);  
  162.       
  163.     mem_pool->memory = (char*)pBuf + mem_pool_struct_size+ sizeof(memory_block) * mem_pool->mem_map_unit_count + sizeof(memory_chunk) * mem_pool->mem_map_pool_count;  
  164.     mem_pool->size = sBufSize – mem_pool_struct_size – sizeof(memory_block) * mem_pool->mem_map_unit_count – sizeof(memory_chunk) * mem_pool->mem_map_pool_count;  
  165.     size_t align = check_align_addr(mem_pool->memory);  
  166.     mem_pool->size -= align;  
  167.     mem_pool->size = check_align_block(mem_pool->size);  
  168.     mem_pool->mem_block_count = mem_pool->size / MINUNITSIZE;  
  169.       
  170.     mem_pool->pfree_mem_chunk_pool = create_list(mem_pool->pfree_mem_chunk_pool, mem_pool->mem_map_pool_count);  
  171.       
  172.     memory_chunk* tmp = front_pop(mem_pool->pfree_mem_chunk_pool);  
  173.     tmp->pre = tmp;  
  174.     tmp->next = tmp;  
  175.     tmp->pfree_mem_addr = NULL;  
  176.     mem_pool->mem_map_pool_count–;  
  177.       
  178.       
  179.     mem_pool->pmem_map[0].count = mem_pool->mem_block_count;  
  180.     mem_pool->pmem_map[0].pmem_chunk = tmp;  
  181.     mem_pool->pmem_map[mem_pool->mem_block_count-1].start = 0;  
  182.       
  183.     tmp->pfree_mem_addr = mem_pool->pmem_map;  
  184.     push_back(mem_pool->pfree_mem_chunk,TMP)
  185.     mem_pool->free_mem_chunk_count = 1;  
  186.     mem_pool->mem_used_size = 0;  
  187.     return mem_pool;  
  188. }  
  189.   
  190.  
  191.   
  192. void ReleaseMemoryPool(PMEMORYPOOL* ppMem)   
  193. {  
  194. }  
  195.   
  196.  
  197.  
  198.  
  199.  
  200.   
  201. void* GetMemory(size_t sMemorySize, PMEMORYPOOL pMem)  
  202. {  
  203.     sMemorySize = check_align_size(sMemorySize);  
  204.     size_t锁上=0
  205.     memory_chunk* tmp = pMem->pfree_mem_chunk;  
  206.     for(锁上=0;锁上< pMem->free_mem_chunk_count; index++)  
  207.     {  
  208.         if (tmp->pfree_mem_addr->count * MINUNITSIZE >= sMemorySize)  
  209.         {             
  210.             break;  
  211.         }  
  212.           
  213.         tmp = tmp->next;  
  214.     }  
  215.       
  216.     if (index == pMem->free_mem_chunk_count)  
  217.     {  
  218.         return NULL;  
  219.     }  
  220.     pMem->mem_used_size += sMemorySize;  
  221.     if (tmp->pfree_mem_addr->count * MINUNITSIZE == sMemorySize)  
  222.     {  
  223.           
  224.         size_t current_index = (tmp->pfree_mem_addr – pMem->pmem_map);  
  225.         delete_chunk(pMem->pfree_mem_chunk,TMP)
  226.         tmp->pfree_mem_addr->pmem_chunk = NULL;  
  227.           
  228.         push_front(pMem->pfree_mem_chunk_pool,TMP)
  229.         pMem->free_mem_chunk_count–;  
  230.         pMem->mem_map_pool_count++;  
  231.           
  232.         return index2addr(pMem, current_index);  
  233.     }  
  234.     else  
  235.     {  
  236.           
  237.           
  238.           
  239.         memory_block copy;  
  240.          = tmp->pfree_mem_addr->count;  
  241.          = tmp;  
  242.           
  243.         memory_block* current_block = tmp->pfree_mem_addr;  
  244.         current_block->count = sMemorySize / MINUNITSIZE;  
  245.         size_t current_index = (current_block – pMem->pmem_map);  
  246.         pMem->pmem_map[current_index+current_block->count-1].start = current_index;  
  247.         current_block->pmem_chunk = NULL;   
  248.           
  249.         pMem->pmem_map[current_index+current_block->count].count =  – current_block->count;  
  250.         pMem->pmem_map[current_index+current_block->count].pmem_chunk = ;  
  251.           
  252.         tmp->pfree_mem_addr = &(pMem->pmem_map[current_index+current_block->count]);  
  253.       
  254.         size_t end_index = current_index +  – 1;  
  255.         pMem->pmem_map[end_index].start = current_index + current_block->count;  
  256.         return index2addr(pMem, current_index);  
  257.     }     
  258. }  
  259.   
  260.  
  261.  
  262.  
  263.   
  264. void FreeMemory(void *ptrMemoryBlock, PMEMORYPOOL pMem)   
  265. {  
  266.     size

发表评论

Your email address will not be published.
*
*