scache

package module
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2022 License: Apache-2.0 Imports: 8 Imported by: 5

README

Segmented Cache (scache)

GoReportCard GoDoc

This library is compatible with Go 1.11+

Please refer to CHANGELOG.md if you encounter breaking changes.

Motivation

The goal of this cache is to provide low latency, zero allocation cache that is able to retain recently used entries that can work with memory or memory mapped files.

Introduction

Segmented Cache is operationally zero allocation as it preallocate memory during initialization. It consists two segments each taking half of the allocated memory:

  • Primary: read/write active
  • Secondary: read only active

In case of entry miss in the active segment, service attempt to locate entry in the secondary segment to rewrite it to active one.

Once active segment reaches limit of allocated memory, or optionally max entries, the secondary segment is promoted to the active, and the active is demoted to the secondary.

This approach double effective memory, but does not require housekeeping on LRU algorithm overhead. To boost write performance, every Set operation append data to the data pool, and old address is invalidated.

This cache has been inspired by BigCache and uses map[uint64]uint32 for key hash to data address mapping. Using non pointers in the map makes GC ommit map content.

See also: How BigCache avoids expensive GC cycles and speeds up concurrent access in Go

Usage


func CacheUsage() {
	var cacheUsageType int
	var cache *scache.Cache
	var err error
	switch cacheUsageType {
	case InMemoryExample:
		cache, err = scache.New(&scache.Config{SizeMb: 256})
		//or 
		cache, err = scache.NewMemCache(256, 0, 0)
	case MemoryMappedFileExample:
		cache, err = scache.New(&scache.Config{SizeMb: 256, Location: "/tmp/data.sch"})
		//or 
		cache, err = scache.NewMmapCache("/tmp/data.sch", 256, 0, 0)
	case InMemoryEntriesExample:
		cache, err = scache.New(&scache.Config{MaxEntries: 5000000, EntrySize: 128})
	}
	if err != nil {
		log.Fatal(err)
	}
	err = cache.Set("keyX", []byte("some value"))
	if err != nil {
		log.Fatal(err)
	}
	value, err := cache.Get("keyX")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("value : %s\n", value)
	err = cache.Delete("keyX")
	if err != nil {
		log.Fatal(err)
	}

}
Benchmark

Benchmark with 256 payload on OSX (2.4 GHz 8-Core Intel Core i9), SSD

BenchmarkService_MemGet-16             	 4182728	       303 ns/op	       7 B/op	       0 allocs/op
BenchmarkService_MMapGet-16            	 4107274	       287 ns/op	       7 B/op	       0 allocs/op
BenchmarkService_MMapGetParallel-16    	28591705	       43.0 ns/op	       7 B/op	       0 allocs/op
BenchmarkService_MemGetParallel-16     	33848409	       39.0 ns/op	       7 B/op	       0 allocs/op
BenchmarkService_MemSet-16             	 5562770	       243 ns/op	       7 B/op	       0 allocs/op
BenchmarkService_MMapSet-16            	 2569632	       575 ns/op	       7 B/op	       0 allocs/op
BenchmarkService_MemSetParallel-16     	15095199	       69.4 ns/op	       7 B/op	       0 allocs/op
BenchmarkService_MMapSetParallel-16    	 2290414	       592 ns/op	       7 B/op	       0 allocs/op

GoCover

GoCover

License

The source code is made available under the terms of the Apache License, Version 2, as stated in the file LICENSE.

Individual files may be made available under their own specific license, all compatible with Apache License, Version 2. Please see individual files for details.

Contributing to SCache

Scache is an open source project and contributors are welcome!

See TODO list

Credits and Acknowledgements

Library Author: Adrian Witas

Documentation

Overview

Package scache defines cache Cache interface and implementation

Index

Examples

Constants

View Source
const (
	//DefaultCacheSizeMb default cache size
	DefaultCacheSizeMb = 1
	//MinShards min shards
	MinShards = 32
	//DefaultShardMapSize default map shard allocation size.
	DefaultShardMapSize = 32 * 1024
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Cache

type Cache struct {
	OnSegmentSwitch
	// contains filtered or unexported fields
}

Cache represents cache service

func New

func New(config *Config) (*Cache, error)

New creates a Cache

Example
package main

import (
	"github.com/viant/scache"
	"log"
)

const (
	InMemoryExample = iota
	MemoryMappedFileExample
	InMemoryEntriesExample
)

func main() {

	var cacheUsageType int
	var cache *scache.Cache
	var err error
	switch cacheUsageType {
	case InMemoryExample:
		cache, err = scache.New(&scache.Config{SizeMb: 256})
		//or
		cache, err = scache.NewMemCache(256, 0, 0)
	case MemoryMappedFileExample:
		cache, err = scache.New(&scache.Config{SizeMb: 256, Location: "/tmp/data.sch"})
		//or
		cache, err = scache.NewMmapCache("/tmp/data.sch", 256, 0, 0)
	case InMemoryEntriesExample:
		cache, err = scache.New(&scache.Config{MaxEntries: 5000000, EntrySize: 128})
	}
	if err != nil {
		log.Fatal(err)
	}
	err = cache.Set("keyX", []byte("some value"))
	if err != nil {
		log.Fatal(err)
	}
	value, err := cache.Get("keyX")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("value : %s\n", value)
	err = cache.Delete("keyX")
	if err != nil {
		log.Fatal(err)
	}
	cache.Close()

}
Output:

func NewMemCache

func NewMemCache(sizeMb, maxEntries, entrySize int) (*Cache, error)

NewMemCache creates a memory backed cache

func NewMmapCache

func NewMmapCache(location string, sizeMb, maxEntries, entrySize int) (*Cache, error)

NewMmapCache creates a memory mapped filed backed cache

func (*Cache) Close

func (s *Cache) Close() (err error)

Close closes the Cache

func (*Cache) Delete

func (s *Cache) Delete(key string) error

Delete deletes key in the cache

func (*Cache) Get

func (s *Cache) Get(key string) ([]byte, error)

Get returns a cache entry for the supplied key or error

func (*Cache) Set

func (s *Cache) Set(key string, value []byte) error

Set sets key with value or error

type Config

type Config struct {
	MaxEntries int //optional upper entries limit in the cache
	EntrySize  int //optional entry size to estimate SizeMb (MaxEntries * EntrySize) when specified
	KeySize    int
	SizeMb     int    //optional max cache size, default 1
	Shards     uint64 //optional segment shards size,  default MAX(32, MaxEntries / 1024*1024)
	Location   string //optional path to mapped memory file
	// contains filtered or unexported fields
}

Config represents cache config

func (*Config) Init

func (c *Config) Init()

Init initialises config

func (*Config) SegmentDataSize

func (c *Config) SegmentDataSize() int

SegmentDataSize returns segments data size (cache always has 2 segments)

type NoSuchKey

type NoSuchKey struct{}

NoSuchKey represents no such key error

func (NoSuchKey) Error

func (e NoSuchKey) Error() string

Error returns key error

type OnSegmentSwitch added in v0.2.0

type OnSegmentSwitch func(index, keys uint32, timeTaken time.Duration)

OnSegmentSwitch function to call when segment switches primary to secondary role

Jump to

Keyboard shortcuts

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