bytespool

package module
v1.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 26, 2024 License: MIT Imports: 7 Imported by: 10

README

💫 BytesPool

Reuse used byte slices to achieve zero allocation.

The existing byte slices are stored in groups according to the capacity length range, and suitable byte slice objects are automatically allocated according to the capacity length when used.

✨ Features

  • Customize the capacity range, or use the default pool.
  • Get byte slices always succeed without panic.
  • Optional length of 0 or fixed-length byte slices.
  • Automatic garbage collection of big-byte slices.
  • BufPool implements the httputil.BufferPool interface.
  • Buffer similar to bytes.Buffer, low-level byte slice multiplexing.
  • High performance, See: Benchmarks.

⚙️ Installation

go get -u github.com/fufuok/bytespool

📚 Examples

Please see: examples

Release warning: examples/warning

Simple reverse proxy: examples/reverse_proxy

package bytespool // import "github.com/fufuok/bytespool"

var DefaultCapacityPools = NewCapacityPools(defaultMinSize, defaultMaxSize)
func Append(buf []byte, elems ...byte) []byte
func AppendString(buf []byte, elems string) []byte
func Clone(buf []byte) []byte
func Get(size int) []byte
func InitDefaultPools(minSize, maxSize int)
func Make(capacity int) []byte
func Make64(capacity uint64) []byte
func MakeMax() []byte
func MakeMin() []byte
func MaxSize() int
func MinSize() int
func New(size int) []byte
func New64(size uint64) []byte
func NewBytes(bs []byte) []byte
func NewMax() []byte
func NewMin() []byte
func NewString(s string) []byte
func Put(buf []byte)
func Release(buf []byte) bool
func RuntimeStats(ps ...*CapacityPools) map[string]uint64
type BufPool struct{ ... }
    func NewBufPool(size int) *BufPool
type CapacityPools struct{ ... }
    func NewCapacityPools(minSize, maxSize int) *CapacityPools
⚡️ Quickstart
package main

import (
	"fmt"

	"github.com/fufuok/bytespool"
)

func main() {
	// Get() is the same as New()
	bs := bytespool.Get(1024)
	// len: 1024, cap: 1024
	fmt.Printf("len: %d, cap: %d\n", len(bs), cap(bs))

	// Put() is the same as Release(), Put it back into the pool after use
	bytespool.Put(bs)

	// len: 0, capacity: 8 (Specified capacity)
	bs = bytespool.Make(8)
	bs = append(bs, "abc"...)
	// len: 3, cap: 8
	fmt.Printf("len: %d, cap: %d\n", len(bs), cap(bs))
	ok := bytespool.Release(bs)
	// true
	fmt.Println(ok)

	// len: 8, capacity: 8 (Fixed length)
	bs = bytespool.New(8)
	copy(bs, "12345678")
	// len: 8, cap: 8, value: 12345678
	fmt.Printf("len: %d, cap: %d, value: %s\n", len(bs), cap(bs), bs)
	bytespool.Release(bs)

	// len: len("xyz"), capacity: 4
	bs = bytespool.NewString("xyz")
	// len: 3, cap: 4, value: xyz
	fmt.Printf("len: %d, cap: %d, value: %s\n", len(bs), cap(bs), bs)
	bytespool.Release(bs)

	// Output:
	// len: 1024, cap: 1024
	// len: 3, cap: 8
	// true
	// len: 8, cap: 8, value: 12345678
	// len: 3, cap: 4, value: xyz
}
⏳ Automated reuse
package main

import (
	"fmt"

	"github.com/fufuok/bytespool"
)

func main() {
	// len: 0, cap: 4 (Specified capacity, automatically adapt to the capacity scale)
	bs3 := bytespool.Make(3)

	bs3 = append(bs3, "123"...)
	fmt.Printf("len: %d, cap: %d, %s\n", len(bs3), cap(bs3), bs3)

	bytespool.Release(bs3)

	// len: 4, cap: 4 (Fixed length)
	bs4 := bytespool.New(4)

	// Reuse of bs3
	fmt.Printf("same array: %v\n", &bs3[0] == &bs4[0])
	// Contain old data
	fmt.Printf("bs3: %s, bs4: %s\n", bs3, bs4[:3])

	copy(bs4, "xy")
	fmt.Printf("len: %d, cap: %d, %s\n", len(bs4), cap(bs4), bs4[:3])

	bytespool.Release(bs4)

	// Output:
	// len: 3, cap: 4, 123
	// same array: true
	// bs3: 123, bs4: 123
	// len: 4, cap: 4, xy3
}
🛠 Reset DefaultPools
package main

import (
	"fmt"

	"github.com/fufuok/bytespool"
)

func main() {
	bytespool.InitDefaultPools(512, 4096)

	bs := bytespool.Make(10)
	fmt.Printf("len: %d, cap: %d\n", len(bs), cap(bs))
	bytespool.Release(bs)

	bs = bytespool.MakeMax()
	fmt.Printf("len: %d, cap: %d\n", len(bs), cap(bs))
	bytespool.Release(bs)

	bs = bytespool.New(10240)
	fmt.Printf("len: %d, cap: %d\n", len(bs), cap(bs))
	ok := bytespool.Release(bs)
	fmt.Printf("Discard: %v\n", !ok)

	// Output:
	// len: 0, cap: 512
	// len: 0, cap: 4096
	// len: 10240, cap: 10240
	// Discard: true
}
🎨 Custom pools
package main

import (
	"github.com/fufuok/bytespool"
)

func main() {
	bspool := bytespool.NewCapacityPools(8, 1024)
	bs := bspool.MakeMax()
	bspool.Release(bs)
	bs = bspool.Make(64)
	bspool.Release(bs)
	bs = bspool.New(128)
	bspool.Release(bs)
}
♾ BufPool

Used to get fixed-length byte slices.

package main

import (
	"fmt"

	"github.com/fufuok/bytespool"
)

func main() {
	bufPool := bytespool.NewBufPool(32 * 1024)
	bs := bufPool.Get()

	data := []byte("test")
	n := copy(bs, data)
	// n: 4, bs: test
	fmt.Printf("n: %d, bs: %s\n", n, bs[:n])

	bufPool.Put(bs)
}
🔥 Buffer

Similar to bytes.Buffer, based on bytespool.

package buffer // import "github.com/fufuok/bytespool/buffer"

var ErrTooLarge = errors.New("buffer: too large") ...
var DefaultBufferSize = 64
func GetReader(bs []byte) *bytes.Reader
func MaxSize() int
func MinSize() int
func Put(bb *Buffer)
func PutReader(r *bytes.Reader)
func Release(bb *Buffer) (ok bool)
func RuntimeStats() map[string]uint64
func SetCapacity(minSize, maxSize int)
type Buffer struct{ ... }
    func Clone(bb *Buffer) *Buffer
    func Get(capacity ...int) *Buffer
    func Make(capacity int) *Buffer
    func Make64(capacity uint64) *Buffer
    func MakeMax() *Buffer
    func MakeMin() *Buffer
    func New(size int) *Buffer
    func NewBuffer(buf []byte) *Buffer
    func NewBytes(bs []byte) *Buffer
    func NewString(s string) *Buffer

Please see:

package main

import (
	"fmt"

	"github.com/fufuok/bytespool/buffer"
)

func main() {
	bb := buffer.Get()

	bb.SetString("1")
	_, _ = bb.WriteString("22")
	_, _ = bb.Write([]byte("333"))
	_ = bb.WriteByte('x')
	bb.Truncate(6)

	fmt.Println("bb:", bb.String())

	bs := bb.Copy()
	bb.SetString("ff")
	fmt.Println("bs:", string(bs))
	fmt.Println("bb:", bb.String())

	// After use, put Buffer back in the pool.
	buffer.Put(bb)
	// or (safe)
	bb.Put()
	// or (safe)
	bb.Release()

	// Output:
	// bb: 122333
	// bs: 122333
	// bb: ff
}

🤖 Benchmarks

byte slices

go test -run=^$ -benchmem -benchtime=1s -count=2 -bench=.
goos: linux
goarch: amd64
pkg: github.com/fufuok/bytespool
cpu: Intel(R) Xeon(R) Gold 6151 CPU @ 3.00GHz
BenchmarkCapacityPools/New-4            56386340                21.24 ns/op            0 B/op          0 allocs/op
BenchmarkCapacityPools/New-4            56503125                21.21 ns/op            0 B/op          0 allocs/op
BenchmarkCapacityPools/Make-4           56200932                21.40 ns/op            0 B/op          0 allocs/op
BenchmarkCapacityPools/Make-4           56215285                21.43 ns/op            0 B/op          0 allocs/op
BenchmarkCapacityPools/MakeMax-4        56522522                21.15 ns/op            0 B/op          0 allocs/op
BenchmarkCapacityPools/MakeMax-4        56000730                21.45 ns/op            0 B/op          0 allocs/op
BenchmarkCapacityPools/New.Parallel-4           217137915                5.480 ns/op           0 B/op          0 allocs/op
BenchmarkCapacityPools/New.Parallel-4           212783748                5.912 ns/op           0 B/op          0 allocs/op
BenchmarkCapacityPools/Make.Parallel-4          212007224                5.541 ns/op           0 B/op          0 allocs/op
BenchmarkCapacityPools/Make.Parallel-4          211065468                5.583 ns/op           0 B/op          0 allocs/op
BenchmarkCapacityPools/MakeMax.Parallel-4       217466509                5.525 ns/op           0 B/op          0 allocs/op
BenchmarkCapacityPools/MakeMax.Parallel-4       218557538                5.524 ns/op           0 B/op          0 allocs/op

Buffer

go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: github.com/fufuok/bytespool/buffer
cpu: Intel(R) Xeon(R) Gold 6151 CPU @ 3.00GHz
BenchmarkBuffer_Write-4         72282802                16.06 ns/op            0 B/op          0 allocs/op
BenchmarkBuffer_Write_Std-4     65271292                18.50 ns/op            0 B/op          0 allocs/op

ff

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultCapacityPools = NewCapacityPools(defaultMinSize, defaultMaxSize)

Functions

func Append added in v1.2.0

func Append(buf []byte, elems ...byte) []byte

func AppendString added in v1.2.0

func AppendString(buf []byte, elems string) []byte

func Clone added in v1.2.0

func Clone(buf []byte) []byte

func Get added in v1.0.1

func Get(size int) []byte

func InitDefaultPools

func InitDefaultPools(minSize, maxSize int)

InitDefaultPools initialize to the default pool.

func Make

func Make(capacity int) []byte

func Make64 added in v0.0.2

func Make64(capacity uint64) []byte

func MakeMax added in v0.0.2

func MakeMax() []byte

func MakeMin added in v0.0.2

func MakeMin() []byte

func MaxSize added in v1.2.0

func MaxSize() int

func MinSize added in v1.2.0

func MinSize() int

func New

func New(size int) []byte
Example
package main

import (
	"fmt"

	"github.com/fufuok/bytespool"
)

func main() {
	// Get() is the same as New()
	bs := bytespool.Get(1024)
	// len: 1024, cap: 1024
	fmt.Printf("len: %d, cap: %d\n", len(bs), cap(bs))

	// Put() is the same as Release(), Put it back into the pool after use
	bytespool.Put(bs)

	// len: 0, cap: 4 (Specified capacity, automatically adapt to the capacity scale)
	bs3 := bytespool.Make(3)

	bs3 = append(bs3, "123"...)
	fmt.Printf("len: %d, cap: %d, %s\n", len(bs3), cap(bs3), bs3)

	bytespool.Release(bs3)

	// len: 4, cap: 4 (Fixed length)
	bs4 := bytespool.New(4)

	// Reuse of bs3
	fmt.Printf("same array: %v\n", &bs3[0] == &bs4[0])
	// Contain old data
	fmt.Printf("bs3: %s, bs4: %s\n", bs3, bs4[:3])

	copy(bs4, "xy")
	fmt.Printf("len: %d, cap: %d, %s\n", len(bs4), cap(bs4), bs4[:3])

	bytespool.Release(bs4)

}
Output:

len: 1024, cap: 1024
len: 3, cap: 4, 123
same array: true
bs3: 123, bs4: 123
len: 4, cap: 4, xy3

func New64 added in v0.0.2

func New64(size uint64) []byte

func NewBytes added in v1.1.1

func NewBytes(bs []byte) []byte

func NewMax added in v0.0.2

func NewMax() []byte

func NewMin added in v0.0.2

func NewMin() []byte

func NewString added in v1.1.1

func NewString(s string) []byte

func Put added in v1.0.1

func Put(buf []byte)

func Release

func Release(buf []byte) bool

func RuntimeStats added in v1.3.0

func RuntimeStats(ps ...*CapacityPools) map[string]uint64

Types

type BufPool added in v1.0.1

type BufPool struct {
	// contains filtered or unexported fields
}

BufPool implements the httputil.BufferPool interface.

func NewBufPool added in v1.0.1

func NewBufPool(size int) *BufPool

func (*BufPool) Get added in v1.0.1

func (b *BufPool) Get() []byte

func (*BufPool) Put added in v1.0.1

func (b *BufPool) Put(buf []byte)

type CapacityPools

type CapacityPools struct {
	// contains filtered or unexported fields
}

func NewCapacityPools

func NewCapacityPools(minSize, maxSize int) *CapacityPools

NewCapacityPools divide into multiple pools according to the capacity scale. Maximum range of byte slice pool: [minCapacity,math.MaxInt32]

func (*CapacityPools) Append added in v1.2.0

func (p *CapacityPools) Append(buf []byte, elems ...byte) []byte

Append similar to the built-in function to append elements to the end of a slice. If there is insufficient capacity, a new underlying array is allocated and the old array is reclaimed.

func (*CapacityPools) AppendString added in v1.2.0

func (p *CapacityPools) AppendString(buf []byte, elems string) []byte

func (*CapacityPools) Clone added in v1.2.0

func (p *CapacityPools) Clone(buf []byte) []byte

Clone return a copy of the byte slice

func (*CapacityPools) Get added in v1.0.1

func (p *CapacityPools) Get(size int) []byte

func (*CapacityPools) Make

func (p *CapacityPools) Make(capacity int) []byte

Make return a byte slice of length 0.

func (*CapacityPools) Make64 added in v0.0.2

func (p *CapacityPools) Make64(capacity uint64) []byte

func (*CapacityPools) MakeMax added in v0.0.2

func (p *CapacityPools) MakeMax() []byte

func (*CapacityPools) MakeMin added in v0.0.2

func (p *CapacityPools) MakeMin() []byte

func (*CapacityPools) MaxSize added in v1.2.0

func (p *CapacityPools) MaxSize() int

func (*CapacityPools) MinSize added in v1.2.0

func (p *CapacityPools) MinSize() int

func (*CapacityPools) New

func (p *CapacityPools) New(size int) (buf []byte)

New return byte slice of the specified size. Warning: may contain old data. Warning: returned buf is never equal to nil

func (*CapacityPools) New64 added in v0.0.2

func (p *CapacityPools) New64(size uint64) []byte

func (*CapacityPools) NewBytes added in v1.1.1

func (p *CapacityPools) NewBytes(bs []byte) []byte

NewBytes returns a byte slice of the specified content.

func (*CapacityPools) NewMax added in v0.0.2

func (p *CapacityPools) NewMax() []byte

func (*CapacityPools) NewMin added in v0.0.2

func (p *CapacityPools) NewMin() []byte

func (*CapacityPools) NewString added in v1.1.1

func (p *CapacityPools) NewString(s string) []byte

NewString returns a byte slice of the specified content.

func (*CapacityPools) Put added in v1.0.1

func (p *CapacityPools) Put(buf []byte)

func (*CapacityPools) Release

func (p *CapacityPools) Release(buf []byte) bool

Release put it back into the byte pool of the corresponding scale. Buffers smaller than the minimum capacity or larger than the maximum capacity are discarded.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL