Documentation ¶
Index ¶
Constants ¶
const ( MiB = 1024 * 1024 GiB = 1024 * MiB )
Variables ¶
var ( ErrInvalidMemoryClass = errors.New("invalid memory class") ErrEarlyMerge = errors.New("not all children have been freed") ErrEmptyPoolOperation = errors.New("operation on empty pool") )
var ( ErrNotEnoughSpace = errors.New("not enough space") ErrNotAllocated = errors.New("no memory allocated at the given offset") )
Functions ¶
func GetMemoryClassSize ¶
GetMemoryClassSize returns size in bytes for a given memory class
func GetMemoryClassType ¶
func GetMemoryClassType(s uint64) classType
GetMemoryClassType returns the minimum memory class type that can hold a device of a given size. The smallest class is 1MB and the largest one is 4GB with 2 bit offset intervals in between, for a total of 7 different classes. This function does not do a validity check
Types ¶
type Allocator ¶
type Allocator interface { Allocate(uint64) (MappedRegion, error) Release(MappedRegion) error }
Allocator is an interface for memory allocation
type MappedRegion ¶
MappedRegion represents a memory block with an offset
type PoolAllocator ¶
type PoolAllocator struct {
// contains filtered or unexported fields
}
PoolAllocator implements a memory allocation strategy similar to buddy-malloc https://github.com/evanw/buddy-malloc/blob/master/buddy-malloc.c We borrow the idea of spanning a tree of fixed size regions on top of a contiguous memory space.
There are a total of 7 different region sizes that can be allocated, with the smallest being 1MB and the largest 4GB (the default maximum size of a Virtual PMem device).
For efficiency and to reduce fragmentation an entire region is allocated when requested. When there's no available region of requested size, we try to allocate more memory for this particular size by splitting the next available larger region into smaller ones, e.g. if there's no region available for size class 0, we try splitting a region from class 1, then class 2 etc, until we are able to do so or hit the upper limit.
func NewPoolMemoryAllocator ¶
func NewPoolMemoryAllocator() PoolAllocator
func (*PoolAllocator) Allocate ¶
func (pa *PoolAllocator) Allocate(size uint64) (MappedRegion, error)
Allocate checks memory region pool for the given `size` and returns a free region with minimal offset, if none available tries expanding matched memory pool.
Internally it's done via moving a region from free pool into a busy pool
func (*PoolAllocator) Release ¶
func (pa *PoolAllocator) Release(reg MappedRegion) error
Release marks a memory region of class `memCls` and offset `offset` as free and tries to merge smaller regions into a bigger one