Skip to content

Commit

Permalink
Fix backend realloc test
Browse files Browse the repository at this point in the history
  • Loading branch information
mgnsk committed Oct 7, 2023
1 parent 80a665e commit 763d3d3
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 55 deletions.
16 changes: 9 additions & 7 deletions internal/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (
"github.com/mgnsk/list"
)

// If cap is 0, map hits this size and then shrinks by half, it is reallocated.
const reallocThreshold = 100000

type record[V any] struct {
value V
deadline int64
Expand Down Expand Up @@ -42,7 +45,6 @@ type Backend[K comparable, V any] struct {
pool sync.Pool
earliestExpireAt int64
cap int
reallocThreshold int // if map hits this size and then shrinks by half, it is reallocated
largestLen int // the map has at least this capacity
needRealloc bool
once sync.Once
Expand All @@ -55,11 +57,10 @@ func NewBackend[K comparable, V any](capacity int) *Backend[K, V] {
<-t.C

return &Backend[K, V]{
timer: t,
done: make(chan struct{}),
xmap: make(RecordMap[K, V], capacity),
cap: capacity,
reallocThreshold: 100000, // 100000 * pointer size
timer: t,
done: make(chan struct{}),
xmap: make(RecordMap[K, V], capacity),
cap: capacity,
}
}

Expand Down Expand Up @@ -201,6 +202,7 @@ func (b *Backend[K, V]) Evict(key K) (Element[V], bool) {
}

// Delete an element from the backend map.
// The element must be uninitialized.
func (b *Backend[K, V]) Delete(key K) {
b.mu.Lock()
defer b.mu.Unlock()
Expand All @@ -210,7 +212,7 @@ func (b *Backend[K, V]) Delete(key K) {

func (b *Backend[K, V]) deleteLocked(key K) {
if b.cap == 0 {
if n := len(b.xmap); n >= b.reallocThreshold || b.largestLen > 0 && n > b.largestLen {
if n := len(b.xmap); n >= reallocThreshold || b.largestLen > 0 && n > b.largestLen {
b.largestLen = n
}
}
Expand Down
55 changes: 7 additions & 48 deletions internal/backend/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,7 @@ import (
. "github.com/onsi/gomega"
)

func TestUnlimitedCapacityMapShrink(t *testing.T) {
t.Run("no realloc", func(t *testing.T) {
g := NewWithT(t)

b := newBackend(size)
g.Expect(b.Len()).To(Equal(size))
g.Expect(getInitializedMapLen(b)).To(Equal(size))

// Evict half-1 of records.
for i := 0; i < size/2-1; i++ {
b.Evict(i)
}

b.RunGC(time.Now().UnixNano())

g.Expect(b.Len()).To(Equal((size / 2) + 1))
g.Expect(getInitializedMapLen(b)).To(Equal((size / 2) + 1))

// TODO: assert that map is the same
})

t.Run("realloc", func(t *testing.T) {
g := NewWithT(t)

b := newBackend(size)
g.Expect(b.Len()).To(Equal(size))
g.Expect(getInitializedMapLen(b)).To(Equal(size))

// Evict half of records.
for i := 0; i < size/2; i++ {
b.Evict(i)
}

b.RunGC(time.Now().UnixNano())

g.Expect(b.Len()).To(Equal(size / 2))
g.Expect(getInitializedMapLen(b)).To(Equal(size / 2))

// TODO: assert that map is new
})
}

// TODO: map len does not contain uninitialized elements
func TestUnlimitedCapacityMapShrinkUninitializedRecords(t *testing.T) {
func TestMapShrinkUninitializedRecords(t *testing.T) {
t.Run("realloc", func(t *testing.T) {
g := NewWithT(t)

Expand All @@ -62,7 +19,6 @@ func TestUnlimitedCapacityMapShrinkUninitializedRecords(t *testing.T) {
// Store uninitialized record.
elem := b.Reserve()
b.LoadOrStore(size-1, elem)
b.Release(elem)

g.Expect(b.Len()).To(Equal(size-1), "list len only initialized elements")
g.Expect(getInitializedMapLen(b)).To(Equal(size-1), "map len only initialized elements")
Expand All @@ -74,12 +30,15 @@ func TestUnlimitedCapacityMapShrinkUninitializedRecords(t *testing.T) {

b.RunGC(time.Now().UnixNano())

g.Expect(b.Len()).To(Equal((size/2)-1), "list len only initialized elements")
g.Expect(getInitializedMapLen(b)).To(Equal((size/2)-1), "map len only initialized elements")
// Initialize the record.
b.Initialize(size-1, 0, 0)

g.Expect(b.Len()).To(Equal((size / 2)), "list len only initialized elements")
g.Expect(getInitializedMapLen(b)).To(Equal((size / 2)), "map len only initialized elements")
})
}

// Note: hardcoded realloc threshold value in the backend.
// Note: backend constant.
const size = 100000

func newBackend(size int) *backend.Backend[int, int] {
Expand Down

0 comments on commit 763d3d3

Please sign in to comment.