|
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- package binary
-
- import "sync"
-
- // Note. This implemention is copy of https://github.com/funny/slab for no dependent
- // Acknowledgments https://github.com/idada
-
- // Pool a mem pool interface
- type Pool interface {
- Alloc(int) []byte
- Free([]byte)
- }
-
- // SyncPool is a sync.Pool base slab allocation memory pool
- type SyncPool struct {
- classes []sync.Pool
- classesSize []int
- minSize int
- maxSize int
- }
-
- // NewSyncPool create a sync.Pool base slab allocation memory pool.
- // minSize is the smallest chunk size.
- // maxSize is the lagest chunk size.
- // factor is used to control growth of chunk size.
- func NewSyncPool(minSize, maxSize, factor int) *SyncPool {
- n := 0
- for chunkSize := minSize; chunkSize <= maxSize; chunkSize *= factor {
- n++
- }
- pool := &SyncPool{
- make([]sync.Pool, n),
- make([]int, n),
- minSize, maxSize,
- }
- n = 0
- for chunkSize := minSize; chunkSize <= maxSize; chunkSize *= factor {
- pool.classesSize[n] = chunkSize
- pool.classes[n].New = func(size int) func() interface{} {
- return func() interface{} {
- buf := make([]byte, size)
- return &buf
- }
- }(chunkSize)
- n++
- }
- return pool
- }
-
- // Alloc try alloc a []byte from internal slab class if no free chunk in slab class Alloc will make one.
- func (pool *SyncPool) Alloc(size int) []byte {
- if size <= pool.maxSize {
- for i := 0; i < len(pool.classesSize); i++ {
- if pool.classesSize[i] >= size {
- mem := pool.classes[i].Get().(*[]byte)
- return (*mem)[:size]
- }
- }
- }
- return make([]byte, size)
- }
-
- // Free release a []byte that alloc from Pool.Alloc.
- func (pool *SyncPool) Free(mem []byte) {
- if size := cap(mem); size <= pool.maxSize {
- for i := 0; i < len(pool.classesSize); i++ {
- if pool.classesSize[i] >= size {
- pool.classes[i].Put(&mem)
- return
- }
- }
- }
- }
|