diff --git a/internal/utils/counters/counter_test.go b/internal/utils/counters/counter_test.go index 8083711..912a7a0 100644 --- a/internal/utils/counters/counter_test.go +++ b/internal/utils/counters/counter_test.go @@ -54,6 +54,7 @@ func TestCounter_GC(t *testing.T) { time.Sleep(1 * time.Second) counter.Increase(1, 20) counter.GC() + t.Log(counter.Get(1)) } func TestCounter_GC2(t *testing.T) { @@ -62,7 +63,7 @@ func TestCounter_GC2(t *testing.T) { } var counter = counters.NewCounter[uint32]().WithGC() - for i := 0; i < 1e5; i++ { + for i := 0; i < 100_000; i++ { counter.Increase(uint64(i), rands.Int(10, 300)) } @@ -93,6 +94,19 @@ func TestCounterMemory(t *testing.T) { t.Log((stat1.TotalAlloc-stat.TotalAlloc)/(1<<20), "MB") t.Log(counter.TotalItems()) + + var gcPause = func() { + var before = time.Now() + runtime.GC() + 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") + } + + gcPause() + + _ = counter.TotalItems() } func BenchmarkCounter_Increase(b *testing.B) { diff --git a/internal/utils/counters/item.go b/internal/utils/counters/item.go index 9dd4d42..7b26934 100644 --- a/internal/utils/counters/item.go +++ b/internal/utils/counters/item.go @@ -7,9 +7,10 @@ import ( ) const spanMaxValue = 10_000_000 +const maxSpans = 10 type Item[T SupportedUIntType] struct { - spans []T + spans [maxSpans + 1]T lastUpdateTime int64 lifeSeconds int64 spanSeconds int64 @@ -19,16 +20,16 @@ func NewItem[T SupportedUIntType](lifeSeconds int) *Item[T] { if lifeSeconds <= 0 { lifeSeconds = 60 } - var spanSeconds = lifeSeconds / 10 + var spanSeconds = lifeSeconds / maxSpans if spanSeconds < 1 { spanSeconds = 1 + } else if lifeSeconds > maxSpans && lifeSeconds%maxSpans != 0 { + spanSeconds++ } - var countSpans = lifeSeconds/spanSeconds + 1 /** prevent index out of bounds **/ return &Item[T]{ lifeSeconds: int64(lifeSeconds), spanSeconds: int64(spanSeconds), - spans: make([]T, countSpans), lastUpdateTime: fasttime.Now().Unix(), } } @@ -119,5 +120,9 @@ func (this *Item[T]) IsExpired(currentTime int64) bool { } func (this *Item[T]) calculateSpanIndex(timestamp int64) int { - return int(timestamp % this.lifeSeconds / this.spanSeconds) + var index = int(timestamp % this.lifeSeconds / this.spanSeconds) + if index > maxSpans-1 { + return maxSpans - 1 + } + return index }