Documentation
¶
Overview ¶
Package bytes provides containers and utilities for working with byte arrays and slices.
Index ¶
- type MirroredBuffer
- func (b *MirroredBuffer) Claim(n int) []byte
- func (b *MirroredBuffer) Commit(n int) int
- func (b *MirroredBuffer) Consume(n int) int
- func (b *MirroredBuffer) Destroy() (err error)
- func (b *MirroredBuffer) FreeSpace() int
- func (b *MirroredBuffer) Full() bool
- func (b *MirroredBuffer) Name() string
- func (b *MirroredBuffer) Prefault()
- func (b *MirroredBuffer) Reset()
- func (b *MirroredBuffer) Size() int
- func (b *MirroredBuffer) UsedSpace() int
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type MirroredBuffer ¶
type MirroredBuffer struct {
// contains filtered or unexported fields
}
MirroredBuffer is a circular FIFO buffer that always returns continuous byte slices. It is well suited for writing protocols on top of streaming transports such as TCP. This buffer does no memory copies or allocations outside of initialization time.
For protocols on top of packet based transports such as UDP, use a BipBuffer instead.
A MirroredBuffer maps a shared memory file twice in the process' virtual memory space. The mappings are sequential. For example, a MirroredBuffer of size `n` will create a shared memory file of size `n` and mmap it twice: once at `addr` and once at `addr+n`. As a result, a MirroredBuffer will uses `2*n` virtual memory and `n` physical memory.
This double mapping allows us to always get a continuous slice of bytes from the buffer. The CPU's memory management unit will do the wrapping for us.
There's a trick employed to make the double mmapping possible - this trick gives us the `addr` above. Given that both mappings need to be sequential, we need to mmap them at fixed virtual memory addresses. We can't arbitrarily choose a virtual address - we have no guarantee that it can hold a mmaping of size `2*n`. That's why we let mmap choose it for us by initially mmaping an area of size `2*n` with MAP_ANONYMOUS | MAP_PRIVATE and no fd. The returned address is then used to mmap the shared memory file twice, consecutively. This is done in the locally defined `remap()` function in the constructor.
func NewMirroredBuffer ¶
func NewMirroredBuffer(size int, prefault bool) (b *MirroredBuffer, err error)
NewMirroredBuffer returns a mirrored buffer of at least the passed size.
The passed size should be a multiple of the system's page size. If it is not, the buffer's size will be rounded up to the nearest multiple of the system's page size, which is usually equal to 4KiB.
If prefault is true, the memory used by the buffer is physically backed after this call. This results in an immediate allocation, visible in the process' resident memory (RSS). Prefaulting can be done post initialization through MirroredBuffer.Prefault().
It is safe to call NewMirroredBuffer concurrently.
func (*MirroredBuffer) Claim ¶
func (b *MirroredBuffer) Claim(n int) []byte
func (*MirroredBuffer) Commit ¶
func (b *MirroredBuffer) Commit(n int) int
func (*MirroredBuffer) Consume ¶
func (b *MirroredBuffer) Consume(n int) int
func (*MirroredBuffer) Destroy ¶
func (b *MirroredBuffer) Destroy() (err error)
func (*MirroredBuffer) FreeSpace ¶
func (b *MirroredBuffer) FreeSpace() int
func (*MirroredBuffer) Full ¶
func (b *MirroredBuffer) Full() bool
func (*MirroredBuffer) Name ¶
func (b *MirroredBuffer) Name() string
func (*MirroredBuffer) Prefault ¶
func (b *MirroredBuffer) Prefault()
Prefault the buffer, forcing physical memory allocation.
func (*MirroredBuffer) Reset ¶
func (b *MirroredBuffer) Reset()
func (*MirroredBuffer) Size ¶
func (b *MirroredBuffer) Size() int
func (*MirroredBuffer) UsedSpace ¶
func (b *MirroredBuffer) UsedSpace() int