diff --git a/internal/ttlcache/piece.go b/internal/ttlcache/piece.go index 40d48c0..2c4251b 100644 --- a/internal/ttlcache/piece.go +++ b/internal/ttlcache/piece.go @@ -24,11 +24,19 @@ func NewPiece[T any](maxItems int) *Piece[T] { } func (this *Piece[T]) Add(key uint64, item *Item[T]) (ok bool) { - this.locker.Lock() + this.locker.RLock() if this.maxItems > 0 && len(this.m) >= this.maxItems { - this.locker.Unlock() + this.locker.RUnlock() return } + this.locker.RUnlock() + + this.locker.Lock() + oldItem, exists := this.m[key] + if exists && oldItem.expiredAt == item.expiredAt { + this.locker.Unlock() + return true + } this.m[key] = item this.locker.Unlock() diff --git a/internal/ttlcache/piece_test.go b/internal/ttlcache/piece_test.go index 4605f37..947244b 100644 --- a/internal/ttlcache/piece_test.go +++ b/internal/ttlcache/piece_test.go @@ -18,6 +18,16 @@ func TestPiece_Add(t *testing.T) { t.Log(piece.Read(1)) } +func TestPiece_Add_Same(t *testing.T) { + piece := NewPiece[int](10) + piece.Add(1, &Item[int]{expiredAt: time.Now().Unix() + 3600}) + piece.Add(1, &Item[int]{expiredAt: time.Now().Unix() + 3600}) + for key, item := range piece.m { + t.Log(key, item.Value) + } + t.Log(piece.Read(1)) +} + func TestPiece_MaxItems(t *testing.T) { piece := NewPiece[int](10) for i := 0; i < 1000; i++ { diff --git a/internal/utils/expires/list_test.go b/internal/utils/expires/list_test.go index dab6a7c..9a8ae3f 100644 --- a/internal/utils/expires/list_test.go +++ b/internal/utils/expires/list_test.go @@ -2,6 +2,7 @@ package expires import ( "github.com/TeaOSLab/EdgeNode/internal/utils/fasttime" + "github.com/TeaOSLab/EdgeNode/internal/utils/testutils" "github.com/iwind/TeaGo/assert" "github.com/iwind/TeaGo/logs" timeutil "github.com/iwind/TeaGo/utils/time" @@ -84,6 +85,10 @@ func TestList_GC_Batch(t *testing.T) { } func TestList_Start_GC(t *testing.T) { + if !testutils.IsSingleTesting() { + return + } + list := NewList() list.Add(1, time.Now().Unix()+1) list.Add(2, time.Now().Unix()+1) @@ -125,6 +130,25 @@ func TestList_ManyItems(t *testing.T) { t.Log(time.Since(now)) } +func TestList_Memory(t *testing.T) { + if !testutils.IsSingleTesting() { + return + } + + var list = NewList() + + testutils.StartMemoryStats(t, func() { + t.Log(list.Count(), "items") + }) + + + for i := 0; i < 10_000_000; i++ { + list.Add(uint64(i), time.Now().Unix()+1800) + } + + time.Sleep(1 * time.Hour) +} + func TestList_Map_Performance(t *testing.T) { t.Log("max uint32", math.MaxUint32) diff --git a/internal/utils/expires/manager.go b/internal/utils/expires/manager.go index cbbb360..352f25f 100644 --- a/internal/utils/expires/manager.go +++ b/internal/utils/expires/manager.go @@ -33,7 +33,7 @@ func (this *Manager) init() { for range this.ticker.C { var currentTime = time.Now().Unix() if lastTimestamp == 0 { - lastTimestamp = currentTime - 3600 + lastTimestamp = currentTime - 86400 // prevent timezone changes } if currentTime >= lastTimestamp {