atomiccache

package module
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 17, 2021 License: MIT Imports: 4 Imported by: 0

README

Atomic Cache

Atomic cache is Golang fast in-memory cache (it wants to be fast - if you want to help, go ahead). Cache using limited nubmer of shards with limited number of containing records. So the memory is limited, but the limit depends on you.

After cache initialization, only one shard is allocated. After that, if there is no left space in shard, new one is allocated. If shard is empty, memory is freed.

There is also support for record expiration. You can set expire time for every record in cache memory.

Example usage

// Initialize cache memory (ac == atomiccache)
cache := ac.New(OptionMaxRecords(512), OptionRecordSize(2048), OptionMaxShards(48))

// Store data in cache memory
cache.Set([]byte("key"), []byte("data"), 500*time.Millisecond)

// Get data from  cache memory
if _, err := cache.Get([]byte("key")); err != nil {
    fmt.Fprintf(os.Stderr, "Cache is empty, but expecting some data: %v", err)
    os.Exit(1)
}

Benchmark

For this benchmark was created memory with following specs: 2048 bytes per record, 2048 records per shard, 128 shards (max). The 2048 bytes was set.

BenchmarkCacheNewMedium-12       	     314	   3804726 ns/op	22686418 B/op	   12402 allocs/op
BenchmarkCacheSetMedium-12       	 1845970	       664.2 ns/op	     129 B/op	       5 allocs/op
BenchmarkCacheGetMedium-12       	 5701435	       209.1 ns/op	      16 B/op	       1 allocs/op

If you want do some special bencharking, go ahead.

AtomicCache vs. BigCache vs. FreeCache vs. HashicorpCache

SET

BenchmarkAtomicCacheSet-12       	 2402160	       519.6 ns/op	     153 B/op	       6 allocs/op
BenchmarkBigCacheSet-12          	 4021484	       376.7 ns/op	      66 B/op	       1 allocs/op
BenchmarkFreeCacheSet-12         	10443246	       100.8 ns/op	       0 B/op	       0 allocs/op
BenchmarkHashicorpCacheSet-12    	 2490759	       498.4 ns/op	     150 B/op	       5 allocs/op

GET

BenchmarkAtomicCacheGet-12       	 6300744	       187.6 ns/op	      16 B/op	       1 allocs/op
BenchmarkBigCacheGet-12          	 3798052	       322.5 ns/op	      37 B/op	       2 allocs/op
BenchmarkFreeCacheGet-12         	 9000188	       127.0 ns/op	      24 B/op	       1 allocs/op
BenchmarkHashicorpCacheGet-12    	 3039728	       405.8 ns/op	       7 B/op	       0 allocs/op

Documentation

Index

Constants

View Source
const (
	// SMSH - Small Shards section
	SMSH = iota + 1
	// MDSH - Medium Shards section
	MDSH
	// LGSH - Large Shards section
	LGSH
)

Constans below are used for shard section identification.

Variables

View Source
var (
	ErrNotFound   = errors.New("record not found")
	ErrDataLimit  = errors.New("cannot create new record: it violates data limit")
	ErrFullMemory = errors.New("cannot create new rocord: memory is full")
)

Internal cache errors

Functions

This section is empty.

Types

type AtomicCache

type AtomicCache struct {
	// RWMutex is used for access to shards array.
	sync.RWMutex

	// Size of byte array used for memory allocation at small shard section.
	RecordSizeSmall int
	// Size of byte array used for memory allocation at medium shard section.
	RecordSizeMedium int
	// Size of byte array used for memory allocation at large shard section.
	RecordSizeLarge int

	// Maximum records per shard.
	MaxRecords int

	// Maximum small shards which can be allocated in cache memory.
	MaxShardsSmall int
	// Maximum medium shards which can be allocated in cache memory.
	MaxShardsMedium int
	// Maximum large shards which can be allocated in cache memory.
	MaxShardsLarge int

	// Garbage collector starter (run garbage collection every X memory sets).
	GcStarter uint32
	// Garbage collector counter for starter.
	GcCounter uint32
	// contains filtered or unexported fields
}

AtomicCache structure represents whole cache memory.

func New

func New(opts ...Option) *AtomicCache

New initialize whole cache memory with one allocated shard.

func (*AtomicCache) Get

func (a *AtomicCache) Get(key interface{}) ([]byte, error)

Get returns list of bytes if record is present in cache memory. If record is not found, then error is returned and list is nil.

func (*AtomicCache) Set

func (a *AtomicCache) Set(key interface{}, data []byte, expire time.Duration) error

Set store data to cache memory. If key/record is already in memory, then data are replaced. If not, it checks if there are some allocated shard with empty space for data. If there is no empty space, new shard is allocated. Otherwise some valid record (FIFO queue) is deleted and new one is stored.

type BufferItem added in v1.0.0

type BufferItem struct {
	Key    interface{}
	Data   []byte
	Expire time.Duration
}

BufferItem is used for buffer, which contains all unattended cache set request.

type LookupRecord

type LookupRecord struct {
	RecordIndex  int
	ShardIndex   int
	ShardSection int
	Expiration   time.Time
}

LookupRecord represents item in lookup table. One record contains index of shard and record. So we can determine which shard access and which record of shard to get. Record also contains expiration time.

type Option

type Option func(*Options)

Option specification for Printer package.

func OptionGcStarter

func OptionGcStarter(option uint32) Option

OptionGcStarter option specification.

func OptionMaxRecords

func OptionMaxRecords(option int) Option

OptionMaxRecords option specification.

func OptionMaxShardsLarge added in v1.0.0

func OptionMaxShardsLarge(option int) Option

OptionMaxShardsLarge option specification.

func OptionMaxShardsMedium added in v1.0.0

func OptionMaxShardsMedium(option int) Option

OptionMaxShardsMedium option specification.

func OptionMaxShardsSmall added in v1.0.0

func OptionMaxShardsSmall(option int) Option

OptionMaxShardsSmall option specification.

func OptionRecordSizeLarge added in v1.0.0

func OptionRecordSizeLarge(option int) Option

OptionRecordSizeLarge option specification.

func OptionRecordSizeMedium added in v1.0.0

func OptionRecordSizeMedium(option int) Option

OptionRecordSizeMedium option specification.

func OptionRecordSizeSmall added in v1.0.0

func OptionRecordSizeSmall(option int) Option

OptionRecordSizeSmall option specification.

type Options

type Options struct {
	// Size of byte array used for memory allocation at small shard section.
	RecordSizeSmall int
	// Size of byte array used for memory allocation at medium shard section.
	RecordSizeMedium int
	// Size of byte array used for memory allocation at large shard section.
	RecordSizeLarge int
	// Maximum records per shard.
	MaxRecords int
	// Maximum small shards which can be allocated in cache memory.
	MaxShardsSmall int
	// Maximum medium shards which can be allocated in cache memory.
	MaxShardsMedium int
	// Maximum large shards which can be allocated in cache memory.
	MaxShardsLarge int
	// Garbage collector starter (run garbage collection every X sets).
	GcStarter uint32
}

Options are used for AtomicCache construct function.

type Record

type Record struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

Record structure represents one record stored in cache memory.

func NewRecord

func NewRecord(size int) *Record

NewRecord initialize one new record and return pointer to them. During initialization is allocated maximum size of record. So we have record which is smaller than maximum size, then we set `alloc` property. It specifies how many bytes are used. It prevents garbage collector to take action.

func (*Record) Free

func (r *Record) Free()

Free set alloc property to 0. Through this action, we empty memory of record without calling garbage collector.

func (*Record) Get

func (r *Record) Get() (data []byte)

Get returns bytes based on size of virtual allocation. It means that it returns only specific count of bytes, based on alloc property. If array on output is empty, then record is not exists.

func (*Record) GetAllocated

func (r *Record) GetAllocated() (size int)

GetAllocated returns size of allocated bytes.

func (*Record) GetDataLength

func (r *Record) GetDataLength() (size int)

GetDataLength returns real size of allocated bytes in memory.

func (*Record) Set

func (r *Record) Set(data []byte)

Set store data to record memory. On output we have bytes, which are copied to record data property and size is set.

type Shard

type Shard struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

Shard structure contains multiple slots for records.

func NewShard

func NewShard(slotCount, slotSize int) *Shard

NewShard initialize list of records with specified size. List is stored in property records and every record has it's own unique id (id is not propagated to record instance). Argument slotCount represents number of records in shard and slotSize represents size of one record.

func (*Shard) Free

func (s *Shard) Free(index int)

Free empty memory specified by index on input and increase slot counter.

func (*Shard) Get

func (s *Shard) Get(index int) (v []byte)

Get returns bytes from shard memory based on index. If array on output is empty, then record is not exists.

func (*Shard) GetSlotsAvail

func (s *Shard) GetSlotsAvail() (cnt int)

GetSlotsAvail returns number of available memory slots of shard.

func (*Shard) IsEmpty

func (s *Shard) IsEmpty() (result bool)

IsEmpty return true if shard has no record registered. Otherwise return false.

func (*Shard) Set

func (s *Shard) Set(data []byte) (i int)

Set store data as a record and decrease slotAvail count. On output it return index of used slot.

type ShardsLookup added in v1.0.0

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

ShardsLookup represents data structure for for each shards section. In each section we have different size of records in that shards.

Jump to

Keyboard shortcuts

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