Skip to content

Commit 2f148ca

Browse files
pdrobnjakclaude
andcommitted
perf: use RWMutex for multiversion store shards (reads use RLock)
GetLatestBeforeIndex accounts for 52.6% of all mutex delay because the plain Mutex forces exclusive locking even for read-only map lookups. Switch to RWMutex so concurrent readers (24 OCC workers) don't block each other. Write paths (SetWriteset, InvalidateWriteset, SetEstimatedWriteset) keep exclusive Lock. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e61ab65 commit 2f148ca

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

sei-cosmos/store/multiversion/store.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const mvShardCount = 64
4545
// guarded by a mutex. This avoids sync.Map's internal hash-trie node
4646
// allocations (~5.4 GB per 120s benchmark with sync.Map).
4747
type mvMapShard struct {
48-
mu sync.Mutex
48+
mu sync.RWMutex
4949
m map[string]MultiVersionValue
5050
}
5151

@@ -114,9 +114,9 @@ func (s *Store) VersionedIndexedStore(index int, incarnation int, abortChannel c
114114
func (s *Store) GetLatest(key []byte) (value MultiVersionValueItem) {
115115
keyString := string(key)
116116
shard := &s.mvShards[mvShardIdx(keyString)]
117-
shard.mu.Lock()
117+
shard.mu.RLock()
118118
mvVal, found := shard.m[keyString]
119-
shard.mu.Unlock()
119+
shard.mu.RUnlock()
120120
if !found {
121121
return nil
122122
}
@@ -131,9 +131,9 @@ func (s *Store) GetLatest(key []byte) (value MultiVersionValueItem) {
131131
func (s *Store) GetLatestBeforeIndex(index int, key []byte) (value MultiVersionValueItem) {
132132
keyString := string(key)
133133
shard := &s.mvShards[mvShardIdx(keyString)]
134-
shard.mu.Lock()
134+
shard.mu.RLock()
135135
mvVal, found := shard.m[keyString]
136-
shard.mu.Unlock()
136+
shard.mu.RUnlock()
137137
if !found {
138138
return nil
139139
}
@@ -148,9 +148,9 @@ func (s *Store) GetLatestBeforeIndex(index int, key []byte) (value MultiVersionV
148148
func (s *Store) Has(index int, key []byte) bool {
149149
keyString := string(key)
150150
shard := &s.mvShards[mvShardIdx(keyString)]
151-
shard.mu.Lock()
151+
shard.mu.RLock()
152152
mvVal, found := shard.m[keyString]
153-
shard.mu.Unlock()
153+
shard.mu.RUnlock()
154154
if !found {
155155
return false
156156
}
@@ -174,9 +174,9 @@ func (s *Store) removeOldWriteset(index int, newWriteSet WriteSet) {
174174
continue
175175
}
176176
shard := &s.mvShards[mvShardIdx(key)]
177-
shard.mu.Lock()
177+
shard.mu.RLock()
178178
mvVal, found := shard.m[key]
179-
shard.mu.Unlock()
179+
shard.mu.RUnlock()
180180
if !found {
181181
continue
182182
}
@@ -469,19 +469,19 @@ func (s *Store) WriteLatestToStore() {
469469
keys := make([]string, 0, 256)
470470
for i := range s.mvShards {
471471
shard := &s.mvShards[i]
472-
shard.mu.Lock()
472+
shard.mu.RLock()
473473
for k := range shard.m {
474474
keys = append(keys, k)
475475
}
476-
shard.mu.Unlock()
476+
shard.mu.RUnlock()
477477
}
478478
sort.Strings(keys)
479479

480480
for _, key := range keys {
481481
shard := &s.mvShards[mvShardIdx(key)]
482-
shard.mu.Lock()
482+
shard.mu.RLock()
483483
mvVal := shard.m[key]
484-
shard.mu.Unlock()
484+
shard.mu.RUnlock()
485485
mvValue, found := mvVal.GetLatestNonEstimate()
486486
if !found {
487487
continue

0 commit comments

Comments
 (0)