Documentation
¶
Overview ¶
Package framecache provides decoded-frame cache implementations for seekable readers.
A Cache used by seekable.Reader need not be safe for concurrent use; the reader serializes access.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Cache ¶
type Cache interface {
// Get returns the frame for frameID, if present. The returned slice must not
// be modified and may alias data passed to Put.
Get(frameID int64) ([]byte, bool)
// Put stores data for frameID, replacing any existing value. The caller must
// not modify data after Put returns.
Put(frameID int64, data []byte)
// Clear removes all cached frames.
Clear()
}
Cache stores decoded frames by seek-table frame ID.
Example (CustomReplacementPolicy) ¶
package main
import (
"fmt"
"github.com/SaveTheRbtz/zstd-seekable-format-go/pkg/framecache"
)
type clockCache struct {
maxFrames int
hand int
items map[int64]int
slots []clockSlot
}
type clockSlot struct {
frameID int64
data []byte
used bool
}
var _ framecache.Cache = (*clockCache)(nil)
func newClockCache(maxFrames int) *clockCache {
return &clockCache{
maxFrames: maxFrames,
items: make(map[int64]int),
}
}
func (c *clockCache) Get(frameID int64) ([]byte, bool) {
index, ok := c.items[frameID]
if !ok {
return nil, false
}
c.slots[index].used = true
return c.slots[index].data, true
}
func (c *clockCache) Put(frameID int64, data []byte) {
if c.maxFrames <= 0 {
return
}
if index, ok := c.items[frameID]; ok {
c.slots[index].data = data
c.slots[index].used = true
return
}
if len(c.slots) < c.maxFrames {
c.items[frameID] = len(c.slots)
c.slots = append(c.slots, clockSlot{frameID: frameID, data: data})
return
}
for {
slot := &c.slots[c.hand]
if slot.used {
slot.used = false
c.advance()
continue
}
delete(c.items, slot.frameID)
*slot = clockSlot{frameID: frameID, data: data}
c.items[frameID] = c.hand
c.advance()
return
}
}
func (c *clockCache) Clear() {
c.hand = 0
c.items = make(map[int64]int)
c.slots = nil
}
func (c *clockCache) advance() {
c.hand = (c.hand + 1) % len(c.slots)
}
func main() {
cache := newClockCache(2)
first := int64(1)
second := int64(2)
third := int64(3)
cache.Put(first, []byte("first"))
cache.Put(second, []byte("second"))
// Touch first so the clock cache gives it a second chance and evicts second.
_, _ = cache.Get(first)
cache.Put(third, []byte("third"))
printFrame("first", cache, first)
printFrame("second", cache, second)
printFrame("third", cache, third)
}
func printFrame(label string, cache framecache.Cache, frameID int64) {
data, ok := cache.Get(frameID)
if !ok {
fmt.Println(label + ": miss")
return
}
fmt.Println(label + ": " + string(data))
}
Output: first: first second: miss third: third
type FIFO ¶
type FIFO struct {
// contains filtered or unexported fields
}
FIFO is a decoded-frame cache using first-in, first-out replacement.
Calls to Get do not affect eviction order.
type LRU ¶
type LRU struct {
// contains filtered or unexported fields
}
LRU is a decoded-frame cache that evicts the least recently used frame.
Put and successful Get calls mark frames most recently used.
type Limits ¶
type Limits struct {
// MaxFrames caps the number of stored frames. Values <= 0 disable storage.
MaxFrames int
// MaxBytes caps decoded bytes stored in the cache. A zero value applies no
// byte limit. If data passed to Put is larger than a positive MaxBytes, Put
// does not store it and removes any existing entry for that frame ID.
MaxBytes uint64
}
Limits configures cache capacity.
type Sieve ¶
type Sieve struct {
// contains filtered or unexported fields
}
Sieve is a decoded-frame cache using the SIEVE-k replacement policy.
Hits and updates increment a per-entry counter, capped at 16. During eviction, entries with positive counters are decremented and kept; the first entry with a zero counter is evicted.