有了tcmalloc和jemalloc,在大多數情況下我們都沒有必要再自己寫通用的記憶體分配器(應該說對於極大多數的程式設計師,都不可能寫出比這
個兩個更好的通用記憶體分配器)。但是,如果對效能有極致的要求,寫乙個比通用記憶體分配器效率更高的池式物件分配器是可能的。
乙個最簡單也高效的實現就是freelist,每次分配的時候從freelist中get乙個,釋放的時候put回去就好了。其實現在單執行緒下是相當簡單的,
也就幾十行**。但是在多執行緒的環境下,問題稍微複雜一點,因為可能有多個執行緒需要操作freelist,那麼就要用鎖去保護這個freelist,每次
get和put的時候都要加鎖顯然會導致freelist的操作效率低下.
我在 block_obj_allocator 中利使用了執行緒本地儲存來減
少鎖的使用,其核心思想是,每個執行緒都有乙個本地的freelist,get和put操作的都是本地的freelist,當本地freelist為空時,向乙個全域性的freelist
,請求一大塊的記憶體,這個時候需要鎖操作。在執行put的時候,如果收集了一定數量的物件,就一次性將一定數量的物件返還給全域性freelist,
這個時候也需要鎖操作。下面提出另外一種實現方式,這個實現要更簡單,其核心思想就是物件由誰分配就由誰負責釋放。
structobj_block
;struct
obj_slot
;
obj_block是乙個記憶體塊管理器,當物件池中沒有物件時,就分配乙個obj_block,然後將buf中的記憶體分成乙個個單獨的obj_slot
新增到obj_block的freelist中.obj_block中記錄了分配執行緒的執行緒id,儲存在thdid變數中.
structpth_allocator
;struct
obj_allocator;
pth_allocator是乙個每執行緒的管理結構,free_block_size記錄了當前管理結構可供分配的obj_block的數量,所有可供分配的obj_block
被新增到free_blocks中,而recy_blocks中儲存了已經沒有可分配物件的obj_block.分配過程是從free_blocks的表頭中獲得乙個obj_block,
然後從obj_block的freelist中彈出乙個空閒的物件,分配出去. 如果分配之後obj_block的freelist為空,則將obj_block從free_blocks中彈
出,新增到recy_blocks中.
這個設計的關鍵在que,它是乙個無鎖演算法實現的棧,這裡之所以使用棧,首先,我們不需要關注釋放的順序,其次無鎖棧的實現最簡單,
開銷最小.
如果釋放執行緒與分配執行緒不是同乙個執行緒,則將要釋放的物件push到que中,由分配執行緒在以後的某個時間裡從que中取出,然後
放回到free_list中,釋放部分的**如下:
void obj_dealloc(struct allocator *allo ,void *ptr)else
lfstack_push(obj->block->que,(struct lnode*)obj);
}
再來看下分配的實現:
void* obj_alloc(struct allocator *allo,int32_t size)if(unlikely(dlist_empty(&pth->free_blocks)))
else
return
__alloc(_allo,pth);
if(unlikely(dlist_empty(&pth->free_blocks)))
__expand(_allo,pth);
return
__alloc(_allo,pth);
}
首先看下本地是否有可供分配的物件,如果有直接呼叫__alloc分配,如果本地沒有則看下que裡有沒有其執行緒釋放的對,如果有將這些物件**到本地
的free_list中,接著再次檢視本地是否有可供分配的物件,如果還是沒有呼叫__expand分配一塊記憶體,建立新的物件,然後再呼叫__alloc分配.
分配器的完整**, 使用方式參看asynserver
物件池模式
物件池是使用成員變數來儲存生成的物件 1 我需要乙個放入池中的物件 public class teacher 2 我需要池中物件的狀態 public class objectstatus 釋放 public void release 檢查是否可用 return public boolean chec...
物件池模式
31.2 物件池模式 31.2.1 定義和類圖 1 定義 物件池是一種設計模式,它通過管理有限物件復用來共享某些稀少或必須付出昂貴代價的資源。2 類圖 31.2.2 物件池的擴充套件介面 1 兩級物件池方式 空閒物件池和已用物件池 使附加一些屬性 如空閒時間 class 3 空閒物件池 存放目前還沒...
JVM 物件分配
1 xmn 新生代記憶體上限值 2 xms 整個堆區初始記憶體分配的大小 3 xmx 堆區記憶體的最大分配大小 4 xx survivorratio 決定eden與乙個survivor大小之比 5 xx pretenuresizethreshold 大物件直接放入老年代,避免在eden區和兩個sur...