优化计数器性能

This commit is contained in:
GoEdgeLab
2023-12-24 15:11:09 +08:00
parent 7f38481b48
commit f14d430754
2 changed files with 25 additions and 6 deletions

View File

@@ -54,6 +54,7 @@ func TestCounter_GC(t *testing.T) {
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
counter.Increase(1, 20) counter.Increase(1, 20)
counter.GC() counter.GC()
t.Log(counter.Get(1))
} }
func TestCounter_GC2(t *testing.T) { func TestCounter_GC2(t *testing.T) {
@@ -62,7 +63,7 @@ func TestCounter_GC2(t *testing.T) {
} }
var counter = counters.NewCounter[uint32]().WithGC() 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)) 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((stat1.TotalAlloc-stat.TotalAlloc)/(1<<20), "MB")
t.Log(counter.TotalItems()) 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) { func BenchmarkCounter_Increase(b *testing.B) {

View File

@@ -7,9 +7,10 @@ import (
) )
const spanMaxValue = 10_000_000 const spanMaxValue = 10_000_000
const maxSpans = 10
type Item[T SupportedUIntType] struct { type Item[T SupportedUIntType] struct {
spans []T spans [maxSpans + 1]T
lastUpdateTime int64 lastUpdateTime int64
lifeSeconds int64 lifeSeconds int64
spanSeconds int64 spanSeconds int64
@@ -19,16 +20,16 @@ func NewItem[T SupportedUIntType](lifeSeconds int) *Item[T] {
if lifeSeconds <= 0 { if lifeSeconds <= 0 {
lifeSeconds = 60 lifeSeconds = 60
} }
var spanSeconds = lifeSeconds / 10 var spanSeconds = lifeSeconds / maxSpans
if spanSeconds < 1 { if spanSeconds < 1 {
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]{ return &Item[T]{
lifeSeconds: int64(lifeSeconds), lifeSeconds: int64(lifeSeconds),
spanSeconds: int64(spanSeconds), spanSeconds: int64(spanSeconds),
spans: make([]T, countSpans),
lastUpdateTime: fasttime.Now().Unix(), lastUpdateTime: fasttime.Now().Unix(),
} }
} }
@@ -119,5 +120,9 @@ func (this *Item[T]) IsExpired(currentTime int64) bool {
} }
func (this *Item[T]) calculateSpanIndex(timestamp int64) int { 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
} }