Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

call evict on replacing value #135

Merged
merged 1 commit into from Jun 21, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions simplelru/lru.go
Expand Up @@ -49,6 +49,9 @@ func (c *LRU[K, V]) Add(key K, value V) (evicted bool) {
// Check for existing item
if ent, ok := c.items[key]; ok {
c.evictList.moveToFront(ent)
if c.onEvict != nil {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is an alternative way that use the lru.ContainsOrAdd interface and check exist boolean return

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious why onEvict needs to be called when adding an existing item?
This caused issue in our use case, where we used gRPC channel as ent.value, and onEvict will close the channel unexpectedly if we try to add that existing channel again

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave it for maintainers of this project to make the call

  • the value is dropped from cache, and some projects rely on evict callback to cleanup (cgo project will also free memory), in some race condition it can cause memory leak and hard to trace
  • in your usecase you can use the somewhat side-effect free ContainsOrAdd

p/s: not sure why you adding back grpc connection to the cache that you just picked from

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand using evict when item is dropped from cache. But in this code block, why do we need to drop from cache? Isn't c.evictList.moveToFront(ent) is enough and the item should still be kept in the cache?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can see right after that the value is overrided with new value, so old value is drop, in your usecase it seems both values are same

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, this behavior came as a surprise for us, as we had a large cache size and didn't expect evict callback to be triggered. Anyways, we can use something like ContainsOrAdd as you suggested

c.onEvict(key, ent.value)
}
ent.value = value
return false
}
Expand Down