71 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			71 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Package iobufpool implements a global segregated-fit pool of buffers for IO.
 | 
						|
//
 | 
						|
// It uses *[]byte instead of []byte to avoid the sync.Pool allocation with Put. Unfortunately, using a pointer to avoid
 | 
						|
// an allocation is purposely not documented. https://github.com/golang/go/issues/16323
 | 
						|
package iobufpool
 | 
						|
 | 
						|
import "sync"
 | 
						|
 | 
						|
const minPoolExpOf2 = 8
 | 
						|
 | 
						|
var pools [18]*sync.Pool
 | 
						|
 | 
						|
func init() {
 | 
						|
	for i := range pools {
 | 
						|
		bufLen := 1 << (minPoolExpOf2 + i)
 | 
						|
		pools[i] = &sync.Pool{
 | 
						|
			New: func() any {
 | 
						|
				buf := make([]byte, bufLen)
 | 
						|
				return &buf
 | 
						|
			},
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Get gets a []byte of len size with cap <= size*2.
 | 
						|
func Get(size int) *[]byte {
 | 
						|
	i := getPoolIdx(size)
 | 
						|
	if i >= len(pools) {
 | 
						|
		buf := make([]byte, size)
 | 
						|
		return &buf
 | 
						|
	}
 | 
						|
 | 
						|
	ptrBuf := (pools[i].Get().(*[]byte))
 | 
						|
	*ptrBuf = (*ptrBuf)[:size]
 | 
						|
 | 
						|
	return ptrBuf
 | 
						|
}
 | 
						|
 | 
						|
func getPoolIdx(size int) int {
 | 
						|
	size--
 | 
						|
	size >>= minPoolExpOf2
 | 
						|
	i := 0
 | 
						|
	for size > 0 {
 | 
						|
		size >>= 1
 | 
						|
		i++
 | 
						|
	}
 | 
						|
 | 
						|
	return i
 | 
						|
}
 | 
						|
 | 
						|
// Put returns buf to the pool.
 | 
						|
func Put(buf *[]byte) {
 | 
						|
	i := putPoolIdx(cap(*buf))
 | 
						|
	if i < 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	pools[i].Put(buf)
 | 
						|
}
 | 
						|
 | 
						|
func putPoolIdx(size int) int {
 | 
						|
	minPoolSize := 1 << minPoolExpOf2
 | 
						|
	for i := range pools {
 | 
						|
		if size == minPoolSize<<i {
 | 
						|
			return i
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return -1
 | 
						|
}
 |