mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-12-13 06:00:26 +08:00
优化计数器内存使用(内存用量减少40%)
This commit is contained in:
@@ -10,7 +10,7 @@ type Item struct {
|
|||||||
lifeSeconds int64
|
lifeSeconds int64
|
||||||
|
|
||||||
spanSeconds int64
|
spanSeconds int64
|
||||||
spans []*Span
|
spans []uint64
|
||||||
|
|
||||||
lastUpdateTime int64
|
lastUpdateTime int64
|
||||||
}
|
}
|
||||||
@@ -24,54 +24,87 @@ func NewItem(lifeSeconds int) *Item {
|
|||||||
spanSeconds = 1
|
spanSeconds = 1
|
||||||
}
|
}
|
||||||
var countSpans = lifeSeconds/spanSeconds + 1 /** prevent index out of bounds **/
|
var countSpans = lifeSeconds/spanSeconds + 1 /** prevent index out of bounds **/
|
||||||
var spans = make([]*Span, countSpans)
|
|
||||||
for i := 0; i < countSpans; i++ {
|
|
||||||
spans[i] = NewSpan()
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Item{
|
return &Item{
|
||||||
lifeSeconds: int64(lifeSeconds),
|
lifeSeconds: int64(lifeSeconds),
|
||||||
spanSeconds: int64(spanSeconds),
|
spanSeconds: int64(spanSeconds),
|
||||||
spans: spans,
|
spans: make([]uint64, countSpans),
|
||||||
lastUpdateTime: fasttime.Now().Unix(),
|
lastUpdateTime: fasttime.Now().Unix(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Item) Increase() uint64 {
|
func (this *Item) Increase() uint64 {
|
||||||
var currentTime = fasttime.Now().Unix()
|
var currentTime = fasttime.Now().Unix()
|
||||||
var spanIndex = int(currentTime % this.lifeSeconds / this.spanSeconds)
|
var currentSpanIndex = this.calculateSpanIndex(currentTime)
|
||||||
var span = this.spans[spanIndex]
|
|
||||||
var roundTime = currentTime / this.spanSeconds * this.spanSeconds
|
|
||||||
|
|
||||||
this.lastUpdateTime = currentTime
|
// return quickly
|
||||||
|
if this.lastUpdateTime == currentTime {
|
||||||
if span.Timestamp < roundTime {
|
this.spans[currentSpanIndex]++
|
||||||
span.Timestamp = roundTime // update time
|
return this.Sum()
|
||||||
span.Count = 0 // reset count
|
|
||||||
}
|
}
|
||||||
span.Count++
|
|
||||||
|
if this.lastUpdateTime > 0 {
|
||||||
|
if currentTime-this.lastUpdateTime > this.lifeSeconds {
|
||||||
|
for index := range this.spans {
|
||||||
|
this.spans[index] = 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var lastSpanIndex = this.calculateSpanIndex(this.lastUpdateTime)
|
||||||
|
var countSpans = len(this.spans)
|
||||||
|
|
||||||
|
// reset values between LAST and CURRENT
|
||||||
|
for index := lastSpanIndex + 1; ; index++ {
|
||||||
|
var realIndex = index % countSpans
|
||||||
|
if realIndex <= currentSpanIndex {
|
||||||
|
this.spans[realIndex] = 0
|
||||||
|
}
|
||||||
|
if realIndex == currentSpanIndex {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spans[currentSpanIndex]++
|
||||||
|
this.lastUpdateTime = currentTime
|
||||||
|
|
||||||
return this.Sum()
|
return this.Sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Item) Sum() uint64 {
|
func (this *Item) Sum() (result uint64) {
|
||||||
var result uint64 = 0
|
if this.lastUpdateTime == 0 {
|
||||||
var currentTimestamp = fasttime.Now().Unix()
|
return 0
|
||||||
for _, span := range this.spans {
|
}
|
||||||
if span.Timestamp >= currentTimestamp-this.lifeSeconds {
|
|
||||||
result += span.Count
|
var currentTime = fasttime.Now().Unix()
|
||||||
|
var currentSpanIndex = this.calculateSpanIndex(currentTime)
|
||||||
|
|
||||||
|
if currentTime-this.lastUpdateTime > this.lifeSeconds {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
var lastSpanIndex = this.calculateSpanIndex(this.lastUpdateTime)
|
||||||
|
var countSpans = len(this.spans)
|
||||||
|
for index := 0; index < countSpans; index++ {
|
||||||
|
if (currentSpanIndex >= lastSpanIndex && (index <= lastSpanIndex || index >= currentSpanIndex /** a >=b **/)) ||
|
||||||
|
(currentSpanIndex < lastSpanIndex && index >= currentSpanIndex && index <= lastSpanIndex /** a < b **/) {
|
||||||
|
result += this.spans[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Item) Reset() {
|
func (this *Item) Reset() {
|
||||||
for _, span := range this.spans {
|
for index := range this.spans {
|
||||||
span.Count = 0
|
this.spans[index] = 0
|
||||||
span.Timestamp = 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Item) IsExpired(currentTime int64) bool {
|
func (this *Item) IsExpired(currentTime int64) bool {
|
||||||
return this.lastUpdateTime < currentTime-this.lifeSeconds-this.spanSeconds
|
return this.lastUpdateTime < currentTime-this.lifeSeconds-this.spanSeconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Item) calculateSpanIndex(timestamp int64) int {
|
||||||
|
return int(timestamp % this.lifeSeconds / this.spanSeconds)
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,27 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestItem_Increase(t *testing.T) {
|
func TestItem_Increase(t *testing.T) {
|
||||||
|
if !testutils.IsSingleTesting() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var item = counters.NewItem(10)
|
||||||
|
t.Log(item.Increase())
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
t.Log(item.Increase())
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
t.Log(item.Increase())
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
t.Log(item.Increase())
|
||||||
|
time.Sleep(6 * time.Second)
|
||||||
|
t.Log(item.Increase())
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
t.Log(item.Increase())
|
||||||
|
time.Sleep(11 * time.Second)
|
||||||
|
t.Log(item.Increase())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestItem_Increase2(t *testing.T) {
|
||||||
// run only under single testing
|
// run only under single testing
|
||||||
if !testutils.IsSingleTesting() {
|
if !testutils.IsSingleTesting() {
|
||||||
return
|
return
|
||||||
@@ -22,7 +43,7 @@ func TestItem_Increase(t *testing.T) {
|
|||||||
|
|
||||||
var item = counters.NewItem(20)
|
var item = counters.NewItem(20)
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
t.Log(item.Increase(), timeutil.Format("i:s"))
|
t.Log(item.Increase(), timeutil.Format("H:i:s"))
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +71,10 @@ func BenchmarkItem_Increase(b *testing.B) {
|
|||||||
|
|
||||||
var item = counters.NewItem(60)
|
var item = counters.NewItem(60)
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
item.Increase()
|
item.Increase()
|
||||||
|
item.Sum()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
|
||||||
|
|
||||||
package counters
|
|
||||||
|
|
||||||
type Span struct {
|
|
||||||
Count uint64
|
|
||||||
Timestamp int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSpan() *Span {
|
|
||||||
return &Span{}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user