mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib/bytesutil: make sure that the cleanup code is performed only by a single goroutine out of many concurrently running goroutines
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3466
This commit is contained in:
parent
ad010726fb
commit
fcee36081b
4 changed files with 41 additions and 12 deletions
|
@ -62,10 +62,8 @@ func (fsm *FastStringMatcher) Match(s string) bool {
|
||||||
s = strings.Clone(s)
|
s = strings.Clone(s)
|
||||||
fsm.m.Store(s, e)
|
fsm.m.Store(s, e)
|
||||||
|
|
||||||
if atomic.LoadUint64(&fsm.lastCleanupTime)+61 < ct {
|
if needCleanup(&fsm.lastCleanupTime, ct) {
|
||||||
// Perform a global cleanup for fsm.m by removing items, which weren't accessed
|
// Perform a global cleanup for fsm.m by removing items, which weren't accessed during the last 5 minutes.
|
||||||
// during the last 5 minutes.
|
|
||||||
atomic.StoreUint64(&fsm.lastCleanupTime, ct)
|
|
||||||
m := &fsm.m
|
m := &fsm.m
|
||||||
m.Range(func(k, v interface{}) bool {
|
m.Range(func(k, v interface{}) bool {
|
||||||
e := v.(*fsmEntry)
|
e := v.(*fsmEntry)
|
||||||
|
@ -78,3 +76,14 @@ func (fsm *FastStringMatcher) Match(s string) bool {
|
||||||
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func needCleanup(lastCleanupTime *uint64, currentTime uint64) bool {
|
||||||
|
lct := atomic.LoadUint64(lastCleanupTime)
|
||||||
|
if lct+61 >= currentTime {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Atomically compare and swap the current time with the lastCleanupTime
|
||||||
|
// in order to guarantee that only a single goroutine out of multiple
|
||||||
|
// concurrently executing goroutines gets true from the call.
|
||||||
|
return atomic.CompareAndSwapUint64(lastCleanupTime, lct, currentTime)
|
||||||
|
}
|
||||||
|
|
|
@ -23,3 +23,27 @@ func TestFastStringMatcher(t *testing.T) {
|
||||||
f("a_b-C", false)
|
f("a_b-C", false)
|
||||||
f("foobar", true)
|
f("foobar", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNeedCleanup(t *testing.T) {
|
||||||
|
f := func(lastCleanupTime, currentTime uint64, resultExpected bool) {
|
||||||
|
t.Helper()
|
||||||
|
lct := lastCleanupTime
|
||||||
|
result := needCleanup(&lct, currentTime)
|
||||||
|
if result != resultExpected {
|
||||||
|
t.Fatalf("unexpected result for needCleanup(%d, %d); got %v; want %v", lastCleanupTime, currentTime, result, resultExpected)
|
||||||
|
}
|
||||||
|
if result {
|
||||||
|
if lct != currentTime {
|
||||||
|
t.Fatalf("unexpected value for lct; got %d; want currentTime=%d", lct, currentTime)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if lct != lastCleanupTime {
|
||||||
|
t.Fatalf("unexpected value for lct; got %d; want lastCleanupTime=%d", lct, lastCleanupTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f(0, 0, false)
|
||||||
|
f(0, 61, false)
|
||||||
|
f(0, 62, true)
|
||||||
|
f(10, 100, true)
|
||||||
|
}
|
||||||
|
|
|
@ -67,10 +67,8 @@ func (fst *FastStringTransformer) Transform(s string) string {
|
||||||
}
|
}
|
||||||
fst.m.Store(s, e)
|
fst.m.Store(s, e)
|
||||||
|
|
||||||
if atomic.LoadUint64(&fst.lastCleanupTime)+61 < ct {
|
if needCleanup(&fst.lastCleanupTime, ct) {
|
||||||
// Perform a global cleanup for fst.m by removing items, which weren't accessed
|
// Perform a global cleanup for fst.m by removing items, which weren't accessed during the last 5 minutes.
|
||||||
// during the last 5 minutes.
|
|
||||||
atomic.StoreUint64(&fst.lastCleanupTime, ct)
|
|
||||||
m := &fst.m
|
m := &fst.m
|
||||||
m.Range(func(k, v interface{}) bool {
|
m.Range(func(k, v interface{}) bool {
|
||||||
e := v.(*fstEntry)
|
e := v.(*fstEntry)
|
||||||
|
|
|
@ -30,10 +30,8 @@ func InternString(s string) string {
|
||||||
}
|
}
|
||||||
internStringsMap.Store(sCopy, e)
|
internStringsMap.Store(sCopy, e)
|
||||||
|
|
||||||
if atomic.LoadUint64(&internStringsMapLastCleanupTime)+61 < ct {
|
if needCleanup(&internStringsMapLastCleanupTime, ct) {
|
||||||
// Perform a global cleanup for internStringsMap by removing items, which weren't accessed
|
// Perform a global cleanup for internStringsMap by removing items, which weren't accessed during the last 5 minutes.
|
||||||
// during the last 5 minutes.
|
|
||||||
atomic.StoreUint64(&internStringsMapLastCleanupTime, ct)
|
|
||||||
m := &internStringsMap
|
m := &internStringsMap
|
||||||
m.Range(func(k, v interface{}) bool {
|
m.Range(func(k, v interface{}) bool {
|
||||||
e := v.(*ismEntry)
|
e := v.(*ismEntry)
|
||||||
|
|
Loading…
Reference in a new issue