golang 內存池


一般來說,內存池都是采用預分配的方式,分為固定大小的和非固定大小塊,固定大小的內存效率高,非固定大小靈活。同時,分為單線程和多線程版的,單線程不需要考慮並發問題。 
一般內存池的實現思想:分配一塊比較大多內存,把這塊內存分成大小相等的塊,即固定大小,第一塊要保存必要的信息,比如nfirst(第一塊可分配到塊),nsize(共分配了多少),nfree(可分配塊大小),pnext(若是內存池不夠,分配一塊growth,pnext指向下一塊),p(保存第一可分配內存塊的地址),同時還需要poolmanage來統一做管理。每一個內存塊的頭兩個字節記錄下一個可分配的內存塊的地址,因為是固定大小的,所以可以根據p和第幾塊算出地址。頭兩個字節分配的好處就是分配之后內存可復用,注意在歸還到內存池的時候頭兩個字節也是需要記錄下一個可分配的內存塊地址。 
這就是內存池的思想,好了,其實今天的主題不是內存池,而是另外一種內存管理的方法,按照塊的大小來分配:

type bys_i struct { E *list.Element T int64 } type ByteSlice struct { P *BytePool size_ int ls_ *list.List ls_m_ map[interface{}]*bys_i ls_l sync.RWMutex zero_ *list.Element } type BytePool struct { // Max int64 T int64 //timeout when gc Beg int End int ms_ map[int]*ByteSlice ms_l sync.RWMutex }

 

 

按照塊的大小來維護,比如map[8]*ByteSlice,map[1024]*ByteSlice,同時,用list來做垃圾回收處理,對每個元素都設置訪問時間T,若是GC時,T(當前)-T(元素)>T(GC條件),從map中delete並從list中remove。這原理跟session很相似,都是用map來存儲,用list來做垃圾回收,因為map讀取速度快,而list插入等操作比較靈活。 
go代碼:

func NewByteSlice(p *BytePool, size int) *ByteSlice {
    ls_ := list.New() zero_ := ls_.PushBack([]byte{}) return &ByteSlice{ P: p, size_: size, ls_: ls_, zero_: zero_, ls_m_: map[interface{}]*bys_i{}, } } func (b *ByteSlice) Alloc() []byte { b.ls_l.Lock() defer b.ls_l.Unlock() var bys []byte tv := b.ls_.Front() if tv == b.zero_ { bys = make([]byte, b.size_) //add count++ fmt.Printf("tv==b.zero_:%v,count:%d\n", &bys[0], count) //end tv = b.ls_.PushBack(bys) b.ls_m_[&bys[0]] = &bys_i{ E: tv, T: util.Now(), } } else { b.ls_.MoveToBack(tv) bys = tv.Value.([]byte) b.ls_m_[&bys[0]].T = util.Now() fmt.Printf("moveToBack:%v,%d,count:%d\n", &bys[0], util.Now(), count) } return bys } func (b *ByteSlice) Free(bys []byte) { b.ls_l.Lock() defer b.ls_l.Unlock() if tv, ok := b.ls_m_[&bys[0]]; ok { tv.T = util.Now() b.ls_.MoveToFront(tv.E) } } func (b *ByteSlice) Size() int64 { // b.ls_l.Lock() // defer b.ls_l.Unlock() return int64(b.ls_.Len()-1) * int64(b.size_) } func (b *ByteSlice) GC() (int, int64) { b.ls_l.Lock() defer b.ls_l.Unlock() tn := util.Now() var rc int = 0 for { tv := b.ls_.Front() if tv == b.zero_ { fmt.Printf("gc tv==b.zero_\n") break } bys := tv.Value.([]byte) rv := &bys[0] if (tn - b.ls_m_[rv].T) > b.P.T { fmt.Printf("gc:%v\n", rv) b.ls_.Remove(tv) delete(b.ls_m_, rv) rc++ } } return rc, b.Size() } 



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM