Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ristretto

Viney
October 14, 2019

 Ristretto

Introduce TinyLFU cache mechanism in Go

Viney

October 14, 2019
Tweet

More Decks by Viney

Other Decks in Technology

Transcript

  1. R st et o A g P a , C

    e , M -B c 2 /1 /1 2
  2. W rk ro nd G ou ca he’s RU +

    m te l ck ! 2 /1 /1 4
  3. R st et o B tt r al o E

    pr ss 2 /1 /1 6
  4. R qu re en 4 C e 4 H c

    -h r 4 M -b (l c g a m u ) 4 S l h n c n g n i e 2 /1 /1 7
  5. 4 F A s 4 H C e n C

    i R n 4 M B g 2 /1 /1 9
  6. K y os 4 A i n l c p

    a i b 4 A a s e k -v 4 H e c d e n l i i 2 /1 /1 1
  7. M mo y ou di g A mi si n

    ol cy ia in LF 2 /1 /1 1
  8. C un Mi S et h 4 D p :

    B l 2 /1 /1 1
  9. E ic io P li y ia am le L

    U // Snippet from the Admission and Eviction Algorithm incHits := p.admit.Estimate(key) for ; room < 0; room = p.evict.roomLeft(cost) { sample = p.evict.fillSample(sample) minKey, minHits, minId := uint64(0), int64(math.MaxInt64), 0 for i, pair := range sample { if hits := p.admit.Estimate(pair.key); hits < minHits { minKey, minHits, minId = pair.key, hits, i } } if incHits < minHits { p.stats.Add(rejectSets, key, 1) return victims, false } p.evict.del(minKey) sample[minId] = sample[len(sample)-1] sample = sample[:len(sample)-1] victims = append(victims, minKey) } 2 /1 /1 1
  10. S or 4 D C 4 N t -l s

    G 4 N l s c e h 2 /1 /1 1
  11. S or (c nt.) 4 s .M 4 s m

    -w m 4 2 s 6 -c s 2 /1 /1 1
  12. H sh 4 r .m 4 n -p e c

    . BenchmarkMemHash-32 200000000 8.88 ns/op BenchmarkFarm-32 100000000 17.9 ns/op BenchmarkSip-32 30000000 41.1 ns/op BenchmarkFnv-32 20000000 70.6 ns/op 2 /1 /1 2
  13. H sh (c nt.) 4 s k 4 w s

    h e s i 2 /1 /1 2
  14. b n h p a n s l h c

    a g n 4 B -W 4 p h 4 b g 2 /1 /1 2
  15. G t 4 s , l n b e 4

    s .P 2 /1 /1 2
  16. G t (c nt.) AddToLossyBuffer(key): stripe := b.pool.Get().(*ringStripe) stripe.Push(key) b.pool.Put(stripe)

    Once buffer fills up, push to channel: select { case p.itemsCh <- keys: p.stats.Add(keepGets, keys[0], uint64(len(keys))) return true default: p.stats.Add(dropGets, keys[0], uint64(len(keys))) return false } p.itemCh processing: func (p *tinyLFU) Push(keys []uint64) { for _, key := range keys { p.Increment(key) } } 2 /1 /1 2
  17. S t 4 c select { case c.setBuf <- &item{key:

    hash, val: val, cost: cost}: return true default: // drop the set and avoid blocking c.stats.Add(dropSets, hash, 1) return false } 2 /1 /1 2
  18. M tr cs 4 p F S 4 1 %

    o d Add: valp := p.all[t] // Avoid false sharing by padding at least 64 bytes of space between two // atomic counters which would be incremented. idx := (hash % 25) * 10 atomic.AddUint64(valp[idx], delta) Read: valp := p.all[t] var total uint64 for i := range valp { total += atomic.LoadUint64(valp[i]) } return total 2 /1 /1 2
  19. H w o func main() { cache, err := ristretto.NewCache(&ristretto.Config{

    NumCounters: 1e7, // Num keys to track frequency of (10M). MaxCost: 1 << 30, // Maximum cost of cache (1GB). BufferItems: 64, // Number of keys per Get buffer. }) if err != nil { panic(err) } cache.Set("key", "value", 1) // set a value // wait for value to pass through buffers time.Sleep(10 * time.Millisecond) value, found := cache.Get("key") if !found { panic("missing value") } fmt.Println(value) cache.Del("key") } 2 /1 /1 3