Closed
Description
What is the issue you are having?
I saw #324 and I'm in the process of implementing MultiGet.
I don't know how to handle [cacheshard.hits] .
- Calling hit causes DeadLock
// entryData used in GetMulti
type entryData struct {
hashedKey uint64
entryKey string
index int
}
...
func (c *BigCache) GetMulti(keys ...string) [][]byte {
var wg sync.WaitGroup
entries := make([][]byte, len(keys))
shardMap := map[*cacheShard][]entryData{}
for i, key := range keys {
hashedKey := c.hash.Sum64(key)
shard := c.getShard(hashedKey)
shardMap[shard] = append(shardMap[shard],
entryData{
hashedKey: hashedKey,
entryKey: key,
index: i,
})
}
wg.Add(len(shardMap))
for shard := range shardMap {
go func(shard *cacheShard) {
defer wg.Done()
shard.getMulti(shardMap[shard], entries)
}(shard)
}
wg.Wait()
return entries
}
...
func (s *cacheShard) getMulti(keys []entryData, entries [][]byte) {
defer s.lock.RUnlock()
s.lock.RLock()
for _, key := range keys {
wrappedEntry, err := s.getWrappedEntry(key.hashedKey)
if err != nil {
continue
}
if entryKey := readKeyFromEntry(wrappedEntry); key.entryKey != entryKey {
s.collision()
if s.isVerbose {
s.logger.Printf("Collision detected. Both %q and %q have the same hash %x", key.entryKey, entryKey, key.hashedKey)
}
continue
}
entry := readEntry(wrappedEntry)
// Causes DeadLock
s.hit(key.hashedKey)
entries[key.index] = entry
}
}
Test
func TestWriteAndGetMultiParallelSameKeyWithStats(t *testing.T) {
t.Parallel()
cache, _ := NewBigCache(Config{
Shards: 4,
LifeWindow: 0,
MaxEntriesInWindow: 1000 * 10 * 60,
MaxEntrySize: 500,
Verbose: true,
StatsEnabled: true,
})
var wg sync.WaitGroup
ntest := 10
n := 3
wg.Add(n)
keys := []string{"key_1", "key_2", "key_3", "key_4"}
values := [][]byte{blob('1', 1024), blob('2', 1024),
blob('3', 1024), blob('4', 1024)}
for i := 0; i < ntest; i++ {
for i, key := range keys {
assertEqual(t, nil, cache.Set(key, values[i]))
}
}
for j := 0; j < n; j++ {
go func() {
for i := 0; i < ntest; i++ {
actual := cache.GetMulti(keys...)
assertEqual(t, values, actual)
}
wg.Done()
}()
}
...
}
- Or am I getting the GetMulti implementation in the wrong direction?
Environment:
- Version (git sha or release ): v3.0.2
- go version: 1.18.4
Metadata
Metadata
Assignees
Labels
No labels