【筆記】對golang的大量小對象的管理真的是無語了……


業務中有這樣一個struct:

type bizData struct{
   A uint64
   B uint64
  C int32
  D uint32
}

雖然沒有實測,但我猜測這樣的對齊方式,這個struct占24字節。
業務中用一個map指向這些對象: map[uint64]*bizData
這樣的存儲對象,一個容器開啟10GB內存,最多存儲60萬左右的對象,容器內存就爆了。

於是自己實現一個簡易的內存池:mempool.go

package mempool

//實現一個按塊擴展的內存池

type memPool struct {
	datas        [][]bizData
	freeNode     chan uint32
	countOfBlock int
}

//NewMemPool 構造內存池對象
func NewMemPool(countOfBlock int) *memPool {
	out := &memPool{
		datas:        [][]bizData{make([]bizData, countOfBlock)},
		freeNode:     make(chan uint32, countOfBlock),
		countOfBlock: countOfBlock,
	}
	for i := 0; i < countOfBlock; i++ {
		out.freeNode <- uint32(i)
	}
	return out
}

func (pool *memPool) moreBlock() {
	pool.datas = append(pool.datas, make([]bizData, pool.countOfBlock))
	ch := make(chan uint32, len(pool.datas)*pool.countOfBlock)
	close(pool.freeNode)
	for item := range pool.freeNode {
		ch <- item
	}
	start := (len(pool.datas) - 1) * pool.countOfBlock
	for i := 0; i < pool.countOfBlock; i++ {
		ch <- uint32(start + i)
	}
	pool.freeNode = ch
}

func (pool *memPool) Get() uint32 {
	if len(pool.freeNode) == 0 {
		pool.moreBlock()
	}
	select {
	case idx := <-pool.freeNode:
		return idx
	default:
		panic("impossible")
	}
}

func (pool *memPool) Put(idx uint32) {
	pool.freeNode <- idx
}

func (pool *memPool) Item(idx uint32) *bizData {
	blockIdx := int(idx) / pool.countOfBlock
	loc := int(idx) % pool.countOfBlock
	return &(pool.datas[blockIdx][loc])
}

然后把對象的引用方式修改為: map[uint64]uint32 //值映射數據塊的下標
使用上面的內存池后,分配250萬小對象,進程內存始終未超過600mb!!

so, 大量小對象的情況下,自己實現內存池更好!


免責聲明!

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



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