From 5b6f572a47078e691d545a3168cb472b51c91d0e Mon Sep 17 00:00:00 2001 From: GoEdgeLab Date: Mon, 25 Dec 2023 16:41:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=A1=E6=95=B0=E5=99=A8?= =?UTF-8?q?=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/utils/counters/counter.go | 17 ++++++++++------- internal/utils/counters/counter_test.go | 9 ++++++--- internal/utils/counters/item.go | 8 ++++++-- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/internal/utils/counters/counter.go b/internal/utils/counters/counter.go index f8207c1..d91b109 100644 --- a/internal/utils/counters/counter.go +++ b/internal/utils/counters/counter.go @@ -22,7 +22,7 @@ type SupportedUIntType interface { type Counter[T SupportedUIntType] struct { countMaps uint64 locker *syncutils.RWMutex - itemMaps []map[uint64]*Item[T] + itemMaps []map[uint64]Item[T] gcTicker *time.Ticker gcIndex int @@ -36,9 +36,9 @@ func NewCounter[T SupportedUIntType]() *Counter[T] { count = 8 } - var itemMaps = []map[uint64]*Item[T]{} + var itemMaps = []map[uint64]Item[T]{} for i := 0; i < count; i++ { - itemMaps = append(itemMaps, map[uint64]*Item[T]{}) + itemMaps = append(itemMaps, map[uint64]Item[T]{}) } var counter = &Counter[T]{ @@ -69,19 +69,22 @@ func (this *Counter[T]) WithGC() *Counter[T] { func (this *Counter[T]) Increase(key uint64, lifeSeconds int) T { var index = int(key % this.countMaps) this.locker.RLock(index) - var item = this.itemMaps[index][key] + var item = this.itemMaps[index][key] // item MUST NOT be pointer this.locker.RUnlock(index) - if item == nil { + if !item.IsOk() { // no need to care about duplication // always insert new item even when itemMap is full item = NewItem[T](lifeSeconds) + var result = item.Increase() this.locker.Lock(index) this.itemMaps[index][key] = item this.locker.Unlock(index) + return result } this.locker.Lock(index) var result = item.Increase() + this.itemMaps[index][key] = item // overwrite this.locker.Unlock(index) return result } @@ -97,7 +100,7 @@ func (this *Counter[T]) Get(key uint64) T { this.locker.RLock(index) defer this.locker.RUnlock(index) var item = this.itemMaps[index][key] - if item != nil { + if item.IsOk() { return item.Sum() } return 0 @@ -115,7 +118,7 @@ func (this *Counter[T]) Reset(key uint64) { var item = this.itemMaps[index][key] this.locker.RUnlock(index) - if item != nil { + if item.IsOk() { this.locker.Lock(index) delete(this.itemMaps[index], key) this.locker.Unlock(index) diff --git a/internal/utils/counters/counter_test.go b/internal/utils/counters/counter_test.go index 2c5376c..772c0ad 100644 --- a/internal/utils/counters/counter_test.go +++ b/internal/utils/counters/counter_test.go @@ -101,7 +101,7 @@ func TestCounterMemory(t *testing.T) { var costSeconds = time.Since(before).Seconds() var stats = &debug.GCStats{} debug.ReadGCStats(stats) - t.Log("GC pause:", stats.PauseTotal.Seconds()*1000, "ms", "cost:", costSeconds*1000, "ms") + t.Log("GC pause:", stats.Pause[0].Seconds()*1000, "ms", "cost:", costSeconds*1000, "ms") } gcPause() @@ -113,12 +113,14 @@ func BenchmarkCounter_Increase(b *testing.B) { runtime.GOMAXPROCS(4) var counter = counters.NewCounter[uint32]() + + b.ReportAllocs() b.ResetTimer() var i uint64 b.RunParallel(func(pb *testing.PB) { for pb.Next() { - counter.Increase(atomic.AddUint64(&i, 1)%1e6, 20) + counter.Increase(atomic.AddUint64(&i, 1)%1_000_000, 20) } }) @@ -138,11 +140,12 @@ func BenchmarkCounter_IncreaseKey(b *testing.B) { }() b.ResetTimer() + b.ReportAllocs() var i uint64 b.RunParallel(func(pb *testing.PB) { for pb.Next() { - counter.IncreaseKey(types.String(atomic.AddUint64(&i, 1)%1e6), 20) + counter.IncreaseKey(types.String(atomic.AddUint64(&i, 1)%1_000_000), 20) } }) diff --git a/internal/utils/counters/item.go b/internal/utils/counters/item.go index 7b26934..a3d4b6a 100644 --- a/internal/utils/counters/item.go +++ b/internal/utils/counters/item.go @@ -16,7 +16,7 @@ type Item[T SupportedUIntType] struct { spanSeconds int64 } -func NewItem[T SupportedUIntType](lifeSeconds int) *Item[T] { +func NewItem[T SupportedUIntType](lifeSeconds int) Item[T] { if lifeSeconds <= 0 { lifeSeconds = 60 } @@ -27,7 +27,7 @@ func NewItem[T SupportedUIntType](lifeSeconds int) *Item[T] { spanSeconds++ } - return &Item[T]{ + return Item[T]{ lifeSeconds: int64(lifeSeconds), spanSeconds: int64(spanSeconds), lastUpdateTime: fasttime.Now().Unix(), @@ -126,3 +126,7 @@ func (this *Item[T]) calculateSpanIndex(timestamp int64) int { } return index } + +func (this *Item[T]) IsOk() bool { + return this.lifeSeconds > 0 +}