chore: [cache-dir-size-fix] Part 3: Add disk size calculator for file cache#4416
chore: [cache-dir-size-fix] Part 3: Add disk size calculator for file cache#4416gargnitingoogle wants to merge 2 commits intogargnitin/cache-dir-size-fix/v2from
Conversation
|
/gemini summary |
Summary of ChangesThis pull request enhances the caching mechanism by introducing a dedicated utility for calculating disk utilization in file caches and refactoring the core LRU cache to support pluggable size calculation strategies. This separation of concerns allows for more accurate and efficient management of disk space for file-backed caches, addressing the complexities of actual disk usage versus logical file sizes. Highlights
Changelog
Activity
|
|
/gemini review |
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
|
/gemini review |
There was a problem hiding this comment.
Code Review
The pull request introduces a FileCacheDiskUtilizationCalculator to abstract cache size calculations, which is a good architectural improvement. However, the implementation has critical issues related to thread safety and correctness in atomic operations, which will cause compilation errors and incorrect behavior under concurrency. I've provided suggestions to fix these issues using a compare-and-swap loop for atomic updates. Additionally, I've suggested some improvements in lru.go to use the new SizeCalculator interface more semantically, enhancing code readability.
| func (c *FileCacheDiskUtilizationCalculator) AddDelta(delta int64) { | ||
| if delta < 0 { | ||
| negDelta := uint64(-delta) | ||
| if negDelta > c.filesSize.Load() { | ||
| c.filesSize.Store(0) | ||
| } else { | ||
| c.filesSize.Add(-negDelta) | ||
| } | ||
| } else { | ||
| c.filesSize.Add(uint64(delta)) | ||
| } | ||
| } |
There was a problem hiding this comment.
The current implementation of AddDelta has two issues. First, c.filesSize.Add(-negDelta) will not compile because the unary minus operator is not defined for uint64. Second, the function is susceptible to a race condition. The value of c.filesSize can change between c.filesSize.Load() and c.filesSize.Store(0) or c.filesSize.Add(...), potentially leading to incorrect size calculations (e.g., wrapping around to a large positive number instead of clamping at zero). A compare-and-swap (CAS) loop should be used to ensure atomicity.
func (c *FileCacheDiskUtilizationCalculator) AddDelta(delta int64) {
if delta == 0 {
return
}
for {
currentVal := c.filesSize.Load()
var newVal uint64
if delta < 0 {
negDelta := uint64(-delta)
if negDelta > currentVal {
newVal = 0
} else {
newVal = currentVal - negDelta
}
} else {
newVal = currentVal + uint64(delta)
}
if c.filesSize.CompareAndSwap(currentVal, newVal) {
return
}
}
}| func (c *FileCacheDiskUtilizationCalculator) EvictEntry(evictedEntry lru.ValueType) { | ||
| c.filesSize.Add(-c.SizeOf(evictedEntry)) | ||
| } |
There was a problem hiding this comment.
The expression -c.SizeOf(evictedEntry) will cause a compilation error because the unary minus operator is not defined for the uint64 type returned by c.SizeOf(). You should use the AddDelta method to correctly handle size subtraction.
| func (c *FileCacheDiskUtilizationCalculator) EvictEntry(evictedEntry lru.ValueType) { | |
| c.filesSize.Add(-c.SizeOf(evictedEntry)) | |
| } | |
| func (c *FileCacheDiskUtilizationCalculator) EvictEntry(evictedEntry lru.ValueType) { | |
| c.AddDelta(-int64(c.SizeOf(evictedEntry))) | |
| } |
| // EvictEntry adds the size for the given entry. | ||
| func (c *FileCacheDiskUtilizationCalculator) InsertEntry(insertedEntry lru.ValueType) { | ||
| c.filesSize.Add(c.SizeOf(insertedEntry)) | ||
| } |
There was a problem hiding this comment.
The comment for InsertEntry is incorrect; it says "EvictEntry". Also, for consistency with EvictEntry and to centralize size update logic, this function should use AddDelta.
| // EvictEntry adds the size for the given entry. | |
| func (c *FileCacheDiskUtilizationCalculator) InsertEntry(insertedEntry lru.ValueType) { | |
| c.filesSize.Add(c.SizeOf(insertedEntry)) | |
| } | |
| // InsertEntry adds the size for the given entry. | |
| func (c *FileCacheDiskUtilizationCalculator) InsertEntry(insertedEntry lru.ValueType) { | |
| c.AddDelta(int64(c.SizeOf(insertedEntry))) | |
| } |
| c.sizeCalculator.AddDelta(-int64(c.sizeCalculator.SizeOf(e.Value.(entry).Value))) | ||
| c.sizeCalculator.AddDelta(int64(valueSize)) |
There was a problem hiding this comment.
Instead of using two AddDelta calls to update the size when an entry is replaced, it would be more semantic and readable to use EvictEntry and InsertEntry. This makes the intent of the code clearer.
| c.sizeCalculator.AddDelta(-int64(c.sizeCalculator.SizeOf(e.Value.(entry).Value))) | |
| c.sizeCalculator.AddDelta(int64(valueSize)) | |
| c.sizeCalculator.EvictEntry(e.Value.(entry).Value) | |
| c.sizeCalculator.InsertEntry(value) |
| e := c.entries.PushFront(entry{key, value}) | ||
| c.index[key] = e | ||
| c.currentSize += valueSize | ||
| c.sizeCalculator.AddDelta(int64(valueSize)) |
There was a problem hiding this comment.
4b48d6e to
4a6bbb9
Compare
b0703f9 to
1b337ac
Compare
4a6bbb9 to
3938291
Compare
1b337ac to
19b157e
Compare
3938291 to
9e7e9c4
Compare
19b157e to
8296b90
Compare
9e7e9c4 to
1d5a9ce
Compare
8296b90 to
8ca046f
Compare
1d5a9ce to
30075a4
Compare
8ca046f to
95670d6
Compare
30075a4 to
d754d78
Compare
95670d6 to
14c98fc
Compare
Description
Cacheininternal/cache/lru/lru.goLink to the issue in case of a bug fix.
b/477828938
Testing details
Any backward incompatible change? If so, please explain.