Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: hashicorp/golang-lru
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v2.0.1
Choose a base ref
...
head repository: hashicorp/golang-lru
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v2.0.2
Choose a head ref
  • 5 commits
  • 13 files changed
  • 4 contributors

Commits on Nov 15, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    efb1d5b View commit details

Commits on Jan 24, 2023

  1. Change fmt.Errorf to errors.New when there is no formatting required (#…

    …120)
    
    Signed-off-by: Sasha Melentyev <sasha@melentyev.io>
    sashamelentyev authored Jan 24, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c857f86 View commit details

Commits on Feb 1, 2023

  1. [COMPLIANCE] Add Copyright and License Headers (#122)

    Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
    hashicorp-copywrite[bot] authored Feb 1, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e2e172e View commit details

Commits on Mar 13, 2023

  1. Update README.md (#124)

    viralmutant authored Mar 13, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    323d74a View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    04222e5 View commit details
Showing with 79 additions and 73 deletions.
  1. +3 −0 .golangci.yml
  2. +10 −8 2q.go
  3. +10 −14 2q_test.go
  4. +1 −1 README.md
  5. +11 −10 arc.go
  6. +10 −14 arc_test.go
  7. +3 −0 doc.go
  8. +3 −0 lru.go
  9. +8 −10 lru_test.go
  10. +6 −6 simplelru/lru.go
  11. +3 −0 simplelru/lru_interface.go
  12. +8 −10 simplelru/lru_test.go
  13. +3 −0 testing.go
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0

linters:
enable:
- megacheck
18 changes: 10 additions & 8 deletions 2q.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package lru

import (
"fmt"
"errors"
"sync"

"github.com/hashicorp/golang-lru/v2/simplelru"
@@ -32,7 +35,7 @@ type TwoQueueCache[K comparable, V any] struct {

recent simplelru.LRUCache[K, V]
frequent simplelru.LRUCache[K, V]
recentEvict simplelru.LRUCache[K, V]
recentEvict simplelru.LRUCache[K, struct{}]
lock sync.RWMutex
}

@@ -46,13 +49,13 @@ func New2Q[K comparable, V any](size int) (*TwoQueueCache[K, V], error) {
// parameter values.
func New2QParams[K comparable, V any](size int, recentRatio, ghostRatio float64) (*TwoQueueCache[K, V], error) {
if size <= 0 {
return nil, fmt.Errorf("invalid size")
return nil, errors.New("invalid size")
}
if recentRatio < 0.0 || recentRatio > 1.0 {
return nil, fmt.Errorf("invalid recent ratio")
return nil, errors.New("invalid recent ratio")
}
if ghostRatio < 0.0 || ghostRatio > 1.0 {
return nil, fmt.Errorf("invalid ghost ratio")
return nil, errors.New("invalid ghost ratio")
}

// Determine the sub-sizes
@@ -68,7 +71,7 @@ func New2QParams[K comparable, V any](size int, recentRatio, ghostRatio float64)
if err != nil {
return nil, err
}
recentEvict, err := simplelru.NewLRU[K, V](evictSize, nil)
recentEvict, err := simplelru.NewLRU[K, struct{}](evictSize, nil)
if err != nil {
return nil, err
}
@@ -153,8 +156,7 @@ func (c *TwoQueueCache[K, V]) ensureSpace(recentEvict bool) {
// the target, evict from there
if recentLen > 0 && (recentLen > c.recentSize || (recentLen == c.recentSize && !recentEvict)) {
k, _, _ := c.recent.RemoveOldest()
var empty V
c.recentEvict.Add(k, empty)
c.recentEvict.Add(k, struct{}{})
return
}

24 changes: 10 additions & 14 deletions 2q_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package lru

import (
@@ -22,8 +25,7 @@ func Benchmark2Q_Rand(b *testing.B) {
if i%2 == 0 {
l.Add(trace[i], trace[i])
} else {
_, ok := l.Get(trace[i])
if ok {
if _, ok := l.Get(trace[i]); ok {
hit++
} else {
miss++
@@ -55,8 +57,7 @@ func Benchmark2Q_Freq(b *testing.B) {
}
var hit, miss int
for i := 0; i < b.N; i++ {
_, ok := l.Get(trace[i])
if ok {
if _, ok := l.Get(trace[i]); ok {
hit++
} else {
miss++
@@ -111,8 +112,7 @@ func Test2Q_Get_RecentToFrequent(t *testing.T) {

// Get should upgrade to t2
for i := 0; i < 128; i++ {
_, ok := l.Get(i)
if !ok {
if _, ok := l.Get(i); !ok {
t.Fatalf("missing: %d", i)
}
}
@@ -125,8 +125,7 @@ func Test2Q_Get_RecentToFrequent(t *testing.T) {

// Get be from t2
for i := 0; i < 128; i++ {
_, ok := l.Get(i)
if !ok {
if _, ok := l.Get(i); !ok {
t.Fatalf("missing: %d", i)
}
}
@@ -238,21 +237,18 @@ func Test2Q(t *testing.T) {
}
}
for i := 0; i < 128; i++ {
_, ok := l.Get(i)
if ok {
if _, ok := l.Get(i); ok {
t.Fatalf("should be evicted")
}
}
for i := 128; i < 256; i++ {
_, ok := l.Get(i)
if !ok {
if _, ok := l.Get(i); !ok {
t.Fatalf("should not be evicted")
}
}
for i := 128; i < 192; i++ {
l.Remove(i)
_, ok := l.Get(i)
if ok {
if _, ok := l.Get(i); ok {
t.Fatalf("should be deleted")
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ Example
Using the LRU is very simple:

```go
l, _ := New(128)
l, _ := New[int, interface{}](128)
for i := 0; i < 256; i++ {
l.Add(i, nil)
}
21 changes: 11 additions & 10 deletions arc.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package lru

import (
@@ -18,23 +21,23 @@ type ARCCache[K comparable, V any] struct {
size int // Size is the total capacity of the cache
p int // P is the dynamic preference towards T1 or T2

t1 simplelru.LRUCache[K, V] // T1 is the LRU for recently accessed items
b1 simplelru.LRUCache[K, V] // B1 is the LRU for evictions from t1
t1 simplelru.LRUCache[K, V] // T1 is the LRU for recently accessed items
b1 simplelru.LRUCache[K, struct{}] // B1 is the LRU for evictions from t1

t2 simplelru.LRUCache[K, V] // T2 is the LRU for frequently accessed items
b2 simplelru.LRUCache[K, V] // B2 is the LRU for evictions from t2
t2 simplelru.LRUCache[K, V] // T2 is the LRU for frequently accessed items
b2 simplelru.LRUCache[K, struct{}] // B2 is the LRU for evictions from t2

lock sync.RWMutex
}

// NewARC creates an ARC of the given size
func NewARC[K comparable, V any](size int) (*ARCCache[K, V], error) {
// Create the sub LRUs
b1, err := simplelru.NewLRU[K, V](size, nil)
b1, err := simplelru.NewLRU[K, struct{}](size, nil)
if err != nil {
return nil, err
}
b2, err := simplelru.NewLRU[K, V](size, nil)
b2, err := simplelru.NewLRU[K, struct{}](size, nil)
if err != nil {
return nil, err
}
@@ -182,14 +185,12 @@ func (c *ARCCache[K, V]) replace(b2ContainsKey bool) {
if t1Len > 0 && (t1Len > c.p || (t1Len == c.p && b2ContainsKey)) {
k, _, ok := c.t1.RemoveOldest()
if ok {
var empty V
c.b1.Add(k, empty)
c.b1.Add(k, struct{}{})
}
} else {
k, _, ok := c.t2.RemoveOldest()
if ok {
var empty V
c.b2.Add(k, empty)
c.b2.Add(k, struct{}{})
}
}
}
24 changes: 10 additions & 14 deletions arc_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package lru

import (
@@ -28,8 +31,7 @@ func BenchmarkARC_Rand(b *testing.B) {
if i%2 == 0 {
l.Add(trace[i], trace[i])
} else {
_, ok := l.Get(trace[i])
if ok {
if _, ok := l.Get(trace[i]); ok {
hit++
} else {
miss++
@@ -61,8 +63,7 @@ func BenchmarkARC_Freq(b *testing.B) {
}
var hit, miss int
for i := 0; i < b.N; i++ {
_, ok := l.Get(trace[i])
if ok {
if _, ok := l.Get(trace[i]); ok {
hit++
} else {
miss++
@@ -121,8 +122,7 @@ func TestARC_Get_RecentToFrequent(t *testing.T) {

// Get should upgrade to t2
for i := 0; i < 128; i++ {
_, ok := l.Get(i)
if !ok {
if _, ok := l.Get(i); !ok {
t.Fatalf("missing: %d", i)
}
}
@@ -135,8 +135,7 @@ func TestARC_Get_RecentToFrequent(t *testing.T) {

// Get be from t2
for i := 0; i < 128; i++ {
_, ok := l.Get(i)
if !ok {
if _, ok := l.Get(i); !ok {
t.Fatalf("missing: %d", i)
}
}
@@ -310,21 +309,18 @@ func TestARC(t *testing.T) {
}
}
for i := 0; i < 128; i++ {
_, ok := l.Get(i)
if ok {
if _, ok := l.Get(i); ok {
t.Fatalf("should be evicted")
}
}
for i := 128; i < 256; i++ {
_, ok := l.Get(i)
if !ok {
if _, ok := l.Get(i); !ok {
t.Fatalf("should not be evicted")
}
}
for i := 128; i < 192; i++ {
l.Remove(i)
_, ok := l.Get(i)
if ok {
if _, ok := l.Get(i); ok {
t.Fatalf("should be deleted")
}
}
3 changes: 3 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

// Package lru provides three different LRU caches of varying sophistication.
//
// Cache is a simple LRU cache. It is based on the
3 changes: 3 additions & 0 deletions lru.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package lru

import (
18 changes: 8 additions & 10 deletions lru_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package lru

import (
@@ -22,8 +25,7 @@ func BenchmarkLRU_Rand(b *testing.B) {
if i%2 == 0 {
l.Add(trace[i], trace[i])
} else {
_, ok := l.Get(trace[i])
if ok {
if _, ok := l.Get(trace[i]); ok {
hit++
} else {
miss++
@@ -55,8 +57,7 @@ func BenchmarkLRU_Freq(b *testing.B) {
}
var hit, miss int
for i := 0; i < b.N; i++ {
_, ok := l.Get(trace[i])
if ok {
if _, ok := l.Get(trace[i]); ok {
hit++
} else {
miss++
@@ -95,21 +96,18 @@ func TestLRU(t *testing.T) {
}
}
for i := 0; i < 128; i++ {
_, ok := l.Get(i)
if ok {
if _, ok := l.Get(i); ok {
t.Fatalf("should be evicted")
}
}
for i := 128; i < 256; i++ {
_, ok := l.Get(i)
if !ok {
if _, ok := l.Get(i); !ok {
t.Fatalf("should not be evicted")
}
}
for i := 128; i < 192; i++ {
l.Remove(i)
_, ok := l.Get(i)
if ok {
if _, ok := l.Get(i); ok {
t.Fatalf("should be deleted")
}
}
12 changes: 6 additions & 6 deletions simplelru/lru.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package simplelru

import (
@@ -100,8 +103,7 @@ func (c *LRU[K, V]) Remove(key K) (present bool) {

// RemoveOldest removes the oldest item from the cache.
func (c *LRU[K, V]) RemoveOldest() (key K, value V, ok bool) {
ent := c.evictList.back()
if ent != nil {
if ent := c.evictList.back(); ent != nil {
c.removeElement(ent)
return ent.key, ent.value, true
}
@@ -110,8 +112,7 @@ func (c *LRU[K, V]) RemoveOldest() (key K, value V, ok bool) {

// GetOldest returns the oldest entry
func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) {
ent := c.evictList.back()
if ent != nil {
if ent := c.evictList.back(); ent != nil {
return ent.key, ent.value, true
}
return
@@ -148,8 +149,7 @@ func (c *LRU[K, V]) Resize(size int) (evicted int) {

// removeOldest removes the oldest item from the cache.
func (c *LRU[K, V]) removeOldest() {
ent := c.evictList.back()
if ent != nil {
if ent := c.evictList.back(); ent != nil {
c.removeElement(ent)
}
}
3 changes: 3 additions & 0 deletions simplelru/lru_interface.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

// Package simplelru provides simple LRU implementation based on build-in container/list.
package simplelru

Loading