bytepool

package module
v3.0.4+incompatible Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2015 License: MIT Imports: 4 Imported by: 13

README

BytePool

A pool for []byte.

Usage:

The pool is thread-safe.

// create a pool of 16 items, each item has a size of 1024
var pool = bytepool.New(1024, 16)


bytes := pool.Checkout()
defer bytes.Release()
bytes.Write([]byte("hello"))
fmt.Prinltn(bytes.String())

Pool Growth

Getting an item from the pool is non-blocking. If the pool is depleted, a new item will be created. However, such dynamically created items are not added back to the pool on release. In other words, the # of items within the pool is fixed.

You can call the Depleted() method for count of how often the pool was depleted. If it's frequently greater than 0, consider increasing the count of items your pool holds.

Item Growth

Items are created with an initial size. Adding more data than this size will cause the item to internally and efficiently convert itself to a bytes.Buffer. However, the growth is not permanent: on Release the initial allocation is re-established (without needing to do a new allocation).

In other words, the total memory used by the bytepool should be size * count. For our above example, that's 16KB. The size will increase as needed, but will always revert back to 16KB (and that 16KB is only initiated once, on startup).

You can call the Expanded() method for a count of how often items were forced to grow beyond the initial size. If it's frequently greater than 0, consider increasing the initial size of the items.

Pool Methods:

  • New(size, count) - Creates a new pool of count items, each initialize to hold size bytes (but able to grow as needed)
  • Checkout() *Bytes - Gets a item which you can write/read from
  • Depleted() int64 - How often the pool was empty. Calling this resets the counter
  • Expanded() int64 - How often items were forced to grow beyond their initial size. Calling this resets the counter
  • Stats() map[string]int64 - Depleted and Expanded in a map

Item Methods:

  • Write(data []byte) (n int, err error)
  • WriteByte(data byte) error
  • WriteString(data string) (n int, err error)
  • Bytes() []byte
  • String() string
  • Len() int
  • ReadFrom(r io.Reader) (n int64, err error)
  • ReadNFrom(n int64, r io.Reader) (m int64, err error)
  • Read(data []byte) (int, error)
  • Release() or Close() - Resets and releases the item back to the pool.
  • Reset() - Resets the item without releasing it back to the pool
  • Position(n uint) - Moves to the specified absolute position. This will grow the buffer if needed.

Numeric Encoding

The WriteUint16, WriteUint32 and WriteUint64 methods can be used to write integers in big endian.

To write using little endian, create a pool using NewEndian or an individual item using NewEndianBytes and pass the binary.LittleEndian object from the stdlib "encoding/binary" package.

Corresponding ReadUint16, ReadUint32 and ReadUint64 are availabl. They return (n, error) where error will be io.EOF if not enough data is available.

Each

It's possible to pre-fill byte items within the pool through the use of the pool's Each and the item's Position functions. You have to take special care to properly Position the item on each checkout.

If you pre-fill the item with more data than the initial capacity, the data will be lost. It makes no sense that you'd define a pool with items having a capacity of 50 bytes., but pre-fill 100 bytes.

For example, say we were writing into a buffer where bytes 4-8 were always the value 30, we could do:

//setup
pool := bytepool.New(256, 10)
pool.Each(func(b *bytepool.Bytes) {
  b.Position(4)
  b.WriteInt32(30)
})


// code that uses the buffer
bytes := pool.Checkout()
bytes.WriteInt32(size) //write into bytes[0:4]
bytes.Position(8)    //skip bytes[4:8] which we already filled
//continue

Documentation

Overview

Package bytepool provides a pool of []byte

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Bytes

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

func NewBytes

func NewBytes(capacity int) *Bytes

func NewEndianBytes

func NewEndianBytes(capacity int, enc binary.ByteOrder) *Bytes

func (*Bytes) Close

func (b *Bytes) Close() error

Alias for Release

func (*Bytes) Position

func (b *Bytes) Position(n uint)

func (*Bytes) ReadByte

func (b *Bytes) ReadByte() (byte, error)

func (*Bytes) ReadFrom

func (b *Bytes) ReadFrom(r io.Reader) (n int64, err error)

Read from the io.Reader

func (*Bytes) ReadNFrom

func (b *Bytes) ReadNFrom(n int64, r io.Reader) (m int64, err error)

Read N bytes from the io.Reader

func (*Bytes) ReadUint16

func (b *Bytes) ReadUint16() (uint16, error)

func (*Bytes) ReadUint32

func (b *Bytes) ReadUint32() (uint32, error)

func (*Bytes) ReadUint64

func (b *Bytes) ReadUint64() (uint64, error)

func (*Bytes) Release

func (b *Bytes) Release()

Release the item back into the pool

func (*Bytes) Reset

func (b *Bytes) Reset()

Reset the object without releasing it

func (*Bytes) SetOnExpand

func (b *Bytes) SetOnExpand(callback func())

Set a custom OnExpand callback (overwriting the one already set). Only useful for when NewBytes is called directly as opposed to through the pool.

func (*Bytes) Write

func (b *Bytes) Write(data []byte) (n int, err error)

Write the bytes

func (*Bytes) WriteByte

func (b *Bytes) WriteByte(d byte) (err error)

Write a byte

func (*Bytes) WriteString

func (b *Bytes) WriteString(str string) (int, error)

Write a string

func (*Bytes) WriteUint16

func (b *Bytes) WriteUint16(n uint16)

func (*Bytes) WriteUint32

func (b *Bytes) WriteUint32(n uint32)

func (*Bytes) WriteUint64

func (b *Bytes) WriteUint64(n uint64)

type Pool

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

func New

func New(size, count int) *Pool

Create a new pool. The pool contains count items. Each item allocates an array of size bytes (but can dynamically grow)

func NewEndian

func NewEndian(size, count int, enc binary.ByteOrder) *Pool

func (*Pool) Checkout

func (p *Pool) Checkout() *Bytes

Get an item from the pool

func (*Pool) Depleted

func (p *Pool) Depleted() int64

Get a count of how often Checkout() was called but no item was available (thus causing an item to be created on the fly) Calling this resets the counter

func (*Pool) Each

func (p *Pool) Each(f func(*Bytes))

Exposes every item currently in the pool If an item is checkout, each won't see it. As such, though thread-safe, you probably only want to call this method on init/startup.

func (*Pool) Expanded

func (p *Pool) Expanded() int64

Get a count of how often we had to expand an item beyond the initially specified size Calling this resets the counter

func (*Pool) Stats

func (p *Pool) Stats() map[string]int64

A map containing the "expanded" and "depleted" count Call this resets both counters

Jump to

Keyboard shortcuts

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