mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-12-23 00:27:55 +08:00
5ce6bbf076
glide has its own requirements. My previous workaround caused me some code checkin errors. Need to fix this.
128 lines
2.5 KiB
Go
128 lines
2.5 KiB
Go
package util
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
ChunkSizes = []int{
|
|
1 << 4, // index 0, 16 bytes, inclusive
|
|
1 << 6, // index 1, 64 bytes
|
|
1 << 8, // index 2, 256 bytes
|
|
1 << 10, // index 3, 1K bytes
|
|
1 << 12, // index 4, 4K bytes
|
|
1 << 14, // index 5, 16K bytes
|
|
1 << 16, // index 6, 64K bytes
|
|
1 << 18, // index 7, 256K bytes
|
|
1 << 20, // index 8, 1M bytes
|
|
1 << 22, // index 9, 4M bytes
|
|
1 << 24, // index 10, 16M bytes
|
|
1 << 26, // index 11, 64M bytes
|
|
1 << 28, // index 12, 128M bytes
|
|
}
|
|
|
|
_DEBUG = false
|
|
)
|
|
|
|
type BytesPool struct {
|
|
chunkPools []*byteChunkPool
|
|
}
|
|
|
|
func NewBytesPool() *BytesPool {
|
|
var bp BytesPool
|
|
for _, size := range ChunkSizes {
|
|
bp.chunkPools = append(bp.chunkPools, newByteChunkPool(size))
|
|
}
|
|
ret := &bp
|
|
if _DEBUG {
|
|
t := time.NewTicker(10 * time.Second)
|
|
go func() {
|
|
for {
|
|
println("buffer:", ret.String())
|
|
<-t.C
|
|
}
|
|
}()
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (m *BytesPool) String() string {
|
|
var buf bytes.Buffer
|
|
for index, size := range ChunkSizes {
|
|
if m.chunkPools[index].count > 0 {
|
|
buf.WriteString(fmt.Sprintf("size:%d count:%d\n", size, m.chunkPools[index].count))
|
|
}
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
func findChunkPoolIndex(size int) int {
|
|
if size <= 0 {
|
|
return -1
|
|
}
|
|
size = (size - 1) >> 4
|
|
ret := 0
|
|
for size > 0 {
|
|
size = size >> 2
|
|
ret = ret + 1
|
|
}
|
|
if ret >= len(ChunkSizes) {
|
|
return -1
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (m *BytesPool) Get(size int) []byte {
|
|
index := findChunkPoolIndex(size)
|
|
// println("get index:", index)
|
|
if index < 0 {
|
|
return make([]byte, size)
|
|
}
|
|
return m.chunkPools[index].Get()
|
|
}
|
|
|
|
func (m *BytesPool) Put(b []byte) {
|
|
index := findChunkPoolIndex(len(b))
|
|
// println("put index:", index)
|
|
if index < 0 {
|
|
return
|
|
}
|
|
m.chunkPools[index].Put(b)
|
|
}
|
|
|
|
// a pool of fix-sized []byte chunks. The pool size is managed by Go GC
|
|
type byteChunkPool struct {
|
|
sync.Pool
|
|
chunkSizeLimit int
|
|
count int64
|
|
}
|
|
|
|
var count int
|
|
|
|
func newByteChunkPool(chunkSizeLimit int) *byteChunkPool {
|
|
var m byteChunkPool
|
|
m.chunkSizeLimit = chunkSizeLimit
|
|
m.Pool.New = func() interface{} {
|
|
count++
|
|
// println("creating []byte size", m.chunkSizeLimit, "new", count, "count", m.count)
|
|
return make([]byte, m.chunkSizeLimit)
|
|
}
|
|
return &m
|
|
}
|
|
|
|
func (m *byteChunkPool) Get() []byte {
|
|
// println("before get size:", m.chunkSizeLimit, "count:", m.count)
|
|
atomic.AddInt64(&m.count, 1)
|
|
return m.Pool.Get().([]byte)
|
|
}
|
|
|
|
func (m *byteChunkPool) Put(b []byte) {
|
|
atomic.AddInt64(&m.count, -1)
|
|
// println("after put get size:", m.chunkSizeLimit, "count:", m.count)
|
|
m.Pool.Put(b)
|
|
}
|