<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          高性能內(nèi)存池實現(xiàn)

          共 4550字,需瀏覽 10分鐘

           ·

          2021-12-23 13:43

          對于從事c/c++開發(fā)的人來說,malloc/new再也熟悉不過了,對于堆上的內(nèi)存分配,都是使用標準庫提供的函數(shù)來進行內(nèi)存分配,而這些函數(shù)最終也會進入到系統(tǒng)調(diào)用(brk等),每次的內(nèi)存申請和釋放,都可能會涉及到底層內(nèi)存數(shù)據(jù)的調(diào)整,所以效率會非常低。如果我們一次申請一塊很大的內(nèi)存塊,后續(xù)所有的內(nèi)存申請和分配,都是基于這一塊內(nèi)存來進行,這樣效率就會提升很多,本文主要就是實現(xiàn)一個高效的固定大小的內(nèi)存池。

          結構

          ? ?圖一

          實現(xiàn)????

          內(nèi)存塊定義:

          typedef?struct?memory_block {        unsigned int size;        unsigned int free_size;        unsigned int first_free;
          struct memory_block *next; char a_data[1];} s_memory_block;

          內(nèi)存池Header:

          typedef?struct?memory_pool {        unsigned int unit_size;        unsigned int init_size;        unsigned int grow_size;        s_memory_block *block;} s_memory_pool;

          初始化內(nèi)存池:

          //此函數(shù)初始化內(nèi)存池Headers_memory_pool?*memory_pool_create(unsigned?int?size) {        s_memory_pool *mp;        mp = (s_memory_pool*)malloc(sizeof(s_memory_pool));        mp->first_block = NULL;        mp->init_size = 10000;        mp->grow_size = 10000;        if(size < sizeof(unsigned int))                mp->obj_size = sizeof(unsigned int);????????//對齊        mp->unit_size = (size + (MEMPOOL_ALIGNMENT-1)) & ~(MEMPOOL_ALIGNMENT-1);        return mp;}

          當初始化之后,內(nèi)存池結構變成:

          ? ?圖二

          從函數(shù)實現(xiàn)內(nèi)容來看,是初始化了內(nèi)存池的頭。

          內(nèi)存分配函數(shù):

          1、從mp的first_block開始,如果其為空,則表明該內(nèi)存池為首次創(chuàng)建,需要分配內(nèi)存塊,并在該內(nèi)存塊內(nèi)進行鏈式初始化,返回該塊的第一小塊地址。

          2、從first_block開始,查找一個有內(nèi)存可分配的block,如果有,則分配,并將first_free指向該塊的下一個地址。

          3、重新建一個block,進行分配,并將該新塊插入到mp的頭部

          void?*memory_alloc(s_memory_pool?*mp)  {
          register unsigned int i; register char *data; //unsigned int length;
          if(mp->first_block == NULL)//memory_pool is NULL {???????????????? s_memory_block *mb; mb = (s_memory_block *)malloc((mp->init_size)*(mp->obj_size) + sizeof(s_memory_block));//create first memory_block if(mb == NULL) { perror("memory allocate failed!\n"); return NULL; }
          /* init the first block */ mb->next = NULL; mb->free_size = mp->init_size - 1; mb->first_free = 1; mb->size = mp->init_size*mp->obj_size;
          mp->first_block = mb;
          data = mb->a_data;
          /* set the mark */ for(i=1; iinit_size; ++i) {???????????????????????//初始化塊,鏈接方式類似于鏈表 }
          return (void *)mb->a_data;????????}?//如圖三 s_memory_block *pm_block = mp->first_block;
          while((pm_block!=NULL) && (pm_block->free_size==0)) { pm_block = pm_block->next; }
          if(pm_block != NULL) { char *pfree = pm_block->a_data + pm_block->first_free * mp->obj_size;????????????????//查找一個可用塊返回????????????????// ......
          return (void *)pfree; } else { if(mp->grow_size == 0) return NULL; s_memory_block *new_block = (s_memory_block *)malloc((mp->grow_size)*(mp->obj_size) + sizeof(s_memory_block));
          if(new_block == NULL) return NULL;
          data = new_block->a_data;
          for(i=1; igrow_size; ++i) {????????????????????????//鏈式 }
          ???????????????//將新塊插入到鏈表頭首部
          return (void *)(new_block->a_data); }}

          釋放函數(shù):

          1、遍歷該內(nèi)存池,查找所要釋放的內(nèi)存塊pfree所在的block

          2、將該block的first指向該pfree的偏移

          3、該pfree的偏移指向之前block的first

          注:2、3處相當于鏈表的插入

          inline void* memory_free(s_memory_pool *mp, void *pfree){  if(mp->first_block == NULL)    return;
          s_memory_block *pm_block = mp->first_block; s_memory_block *pm_pre_block = mp->first_block;
          /* research the memory_block which the pfree in */ while(pm_block && ((unsigned int)pfree<(unsigned int)pm_block->a_data || (unsigned int)pfree>((unsigned int)pm_block->a_data+pm_block->size))) { //pm_pre_block = pm_block; pm_block = pm_block->next; if(pm_block == NULL) return NULL; }
          ??//獲取偏移地址 unsigned int offset = pfree -(void*) pm_block->a_data;
          if((offset&(mp->obj_size -1)) > 0) return pfree;??//將釋放的內(nèi)存塊返回給內(nèi)存池對應的Block塊 pm_block->free_size++; *((unsigned int *)pfree) = pm_block->first_free; pm_block->first_free=(unsigned int)(offset/mp->obj_size);
          ??return?NULL;
          }

          圖三

          當內(nèi)存池為空的時候,也就是首次調(diào)用memory_alloc函數(shù)時候,會創(chuàng)建一個新的Block,并對這個Block進行初始化,然后返回首塊地址?。

          當?shù)诙握{(diào)用memory_alloc之后,如圖四所示。

          當?shù)谌握{(diào)用memory_alloc之后,如圖五所示。? ?????????????????????????????????????????



          圖四

          圖五

          圖六

          當釋放第二次分配的內(nèi)存之后,整個內(nèi)存塊鏈表如圖六所示。

          圖八

          當現(xiàn)在所有的Block里面都沒有可用內(nèi)存之后,就重新申請一塊Block,并插入到Header的頭部,如圖八所示。


          內(nèi)存池數(shù)據(jù)結果:

          與庫函數(shù)malloc相比,性能提升了大概25%左右


          注:本文旨在于提供一種設計思路,在本文實現(xiàn)的內(nèi)存池,僅僅支持單線程,固定大小的,讀者可以針對該思路,進行改進


          瀏覽 50
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人黄色在线观看 | 三级av二区 | 五月亚洲| 91精品国久久久久久无码一区二区三区 | 国产精品久久精品 |