Skip to content

Commit 9dfb87c

Browse files
authored
infoschema: change sieve Get() function Mutex to RWMutex (#58243)
close #58227
1 parent df0c5d1 commit 9dfb87c

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

pkg/infoschema/sieve.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"container/list"
1919
"context"
2020
"sync"
21+
"sync/atomic"
2122

2223
"github.com/pingcap/failpoint"
2324
"github.com/pingcap/tidb/pkg/infoschema/internal"
@@ -27,7 +28,7 @@ import (
2728
type entry[K comparable, V any] struct {
2829
key K
2930
value V
30-
visited bool
31+
visited atomic.Bool
3132
element *list.Element
3233
size uint64
3334
}
@@ -48,7 +49,7 @@ func (t *entry[K, V]) Size() uint64 {
4849
type Sieve[K comparable, V any] struct {
4950
ctx context.Context
5051
cancel context.CancelFunc
51-
mu sync.Mutex
52+
mu sync.RWMutex
5253
size uint64
5354
// capacity can be set to zero for disabling infoschema v2
5455
capacity uint64
@@ -132,7 +133,7 @@ func (s *Sieve[K, V]) Set(key K, value V) {
132133

133134
if e, ok := s.items[key]; ok {
134135
e.value = value
135-
e.visited = true
136+
e.visited.Store(true)
136137
return
137138
}
138139

@@ -156,10 +157,13 @@ func (s *Sieve[K, V]) Get(key K) (value V, ok bool) {
156157
var v V
157158
failpoint.Return(v, false)
158159
})
159-
s.mu.Lock()
160-
defer s.mu.Unlock()
161-
if e, ok := s.items[key]; ok {
162-
e.visited = true
160+
161+
s.mu.RLock()
162+
e, ok := s.items[key]
163+
s.mu.RUnlock()
164+
165+
if ok {
166+
e.visited.Store(true)
163167
s.hook.onHit()
164168
return e.value, true
165169
}
@@ -254,8 +258,8 @@ func (s *Sieve[K, V]) evict() {
254258
panic("sieve: evicting non-existent element")
255259
}
256260

257-
for el.visited {
258-
el.visited = false
261+
for el.visited.Load() {
262+
el.visited.Store(false)
259263
o = o.Prev()
260264
if o == nil {
261265
o = s.ll.Back()

pkg/infoschema/sieve_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
package infoschema
1616

1717
import (
18+
"context"
19+
"math/rand"
20+
"sync/atomic"
1821
"testing"
1922

2023
"github.com/pingcap/tidb/pkg/util/size"
@@ -135,3 +138,43 @@ func TestPurge(t *testing.T) {
135138

136139
cache.Close()
137140
}
141+
142+
func BenchmarkSieveGet(b *testing.B) {
143+
c := newSieve[int, int](8192)
144+
ent := make([]int, b.N)
145+
for i := 0; i < b.N; i++ {
146+
var k int
147+
if i%2 == 0 {
148+
k = int(rand.Int63() % 16384)
149+
} else {
150+
k = int(rand.Int63() % 32768)
151+
}
152+
c.Set(k, k)
153+
ent[i] = k
154+
}
155+
156+
ctx, cancel := context.WithCancel(context.Background())
157+
go func() {
158+
for {
159+
v := int(rand.Int63() % 8192)
160+
c.Set(v, v)
161+
if ctx.Err() != nil {
162+
return
163+
}
164+
}
165+
}()
166+
167+
b.ResetTimer()
168+
169+
var hit, miss int64
170+
for i := 0; i < b.N; i++ {
171+
if _, ok := c.Get(ent[i]); ok {
172+
atomic.AddInt64(&hit, 1)
173+
} else {
174+
atomic.AddInt64(&miss, 1)
175+
}
176+
}
177+
178+
b.Logf("%d: hit %d, miss %d, ratio %4.2f", b.N, hit, miss, float64(hit)/float64(hit+miss))
179+
cancel()
180+
}

0 commit comments

Comments
 (0)