Conversation
ehnuje
commented
Jan 31, 2021
- Spawned from Iterator support? #43 - Iterator support?
- I've checked the previous iterator-like implementation, Add VisitAllEntries method to iterate all entries in cache. #3
- This implementation avoids iterating the whole cache from a single function call. Instead, it copies keys from a bucket, not whole keys from a cache. And then it uses the copied key to retrieve the value from the cache.
|
LTGM! From the looks of it, this is a highly desirable feature and this PR looks pretty solid! |
|
When the number of traversals I traverse is large enough, it will cause the array to go out of bounds and cause a panic. Can you help me check it out? |
| chunkIdx := idx / chunkSize | ||
| chunk := b.chunks[chunkIdx] | ||
|
|
||
| kvLenBuf := chunk[idx : idx+4] |
There was a problem hiding this comment.
This may cause the array to go out of bounds and generate Panic
There was a problem hiding this comment.
Adding this line of code may solve the problem, can you help me take a look? idx = idx % chunkSize
There was a problem hiding this comment.
Yes, I think idx %= chunkSize should be added like in (*bucket).Get().
FYI, here is the panic log:
2026/03/31 08:19:17 [Recovery] 2026/03/31 - 08:19:17 panic recovered:
runtime error: slice bounds out of range [:144261] with capacity 65536
Implement cache dumping with fastcache iterator. Will switch back to official when the iterator PR is merged. See VictoriaMetrics/fastcache#44
| idx := v & ((1 << bucketSizeBits) - 1) | ||
| gen := v >> bucketSizeBits | ||
|
|
||
| if gen == b.gen && idx < b.idx || gen+1 == b.gen && idx >= b.idx { |
There was a problem hiding this comment.
I believe the condition should be:
gen == bGen && idx < b.idx || gen+1 == bGen && idx >= b.idx || gen == maxGen && bGen == 1 && idx >= b.idxgen == maxGen && bGen == 1 && idx >= b.idx is the situation where maxGen is reached on the last wrap and the current generation is reset to 1.
| cache *Cache | ||
| currBucketSize int | ||
| currBucketIdx int | ||
| currBucketKeys [][]byte |
There was a problem hiding this comment.
Consider storing (hash, idx) pairs in iterator instead of bucket keys? Let SetNext() verify key hash on retrieval?
This removes the necessity of copying all the keys from the bucket.
| } | ||
|
|
||
| // SetNext moves to the next element and returns true if the value exists. | ||
| func (it *Iterator) SetNext() bool { |
There was a problem hiding this comment.
Currently SetNext() allocates a new slice when retrieving the value. Consider using a single GetNext(kDst []byte, vDst []byte) ([]byte, []byte, bool) similar to (*Cache).Get for zero-copy?