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

Switch LRU to internal cache implementation #20

Closed
wants to merge 3 commits into from
Closed

Switch LRU to internal cache implementation #20

wants to merge 3 commits into from

Conversation

paskal
Copy link
Collaborator

@paskal paskal commented May 4, 2020

This version is basically hybrid of ours and hashicorp/golang-lru. It turned out we still support expirable LRU cache, we just don't use it in lcw yet.

Copy link
Member

@umputun umputun left a comment

Choose a reason for hiding this comment

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

adding linked list as a container for map ordering is not a bad idea, but keeping list elements in map feels very wrong to me.

@@ -24,20 +24,20 @@ type LoadingCache struct {
onEvicted func(key string, value interface{})

sync.Mutex
data map[string]*cacheItem
data map[string]*list.Element
Copy link
Member

Choose a reason for hiding this comment

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

I get the idea, but hate this implimentation. Keeping list element, wich is a part of linked list container, inside of map looks strange and confusing

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Other way around is list element inside CacheItem, I did it in #21.

@@ -24,20 +24,20 @@ type LoadingCache struct {
onEvicted func(key string, value interface{})

sync.Mutex
data map[string]*cacheItem
data map[string]*list.Element
evictList *list.List
Copy link
Member

Choose a reason for hiding this comment

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

I'd suggest to change this evictList to list of keys. This way we will duplicate keys but the evictList can be a nice way to add sorting to the primary map, For lru it will push to top on access, for TTL it will be sorted natively by insertion order.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We have "natural" sorting for both LRU and LRC you mentioned already in place.

*list.Element is used because Go lacks "generics", I'll need to copy-paste list implementation for our type to change it's values types. Do you think we should do that?

Copy link
Member

Choose a reason for hiding this comment

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

no, my suggestion was to keep a sorted list for evicted keys only and leave items alone. I.e. data will be map of naked interface{} (as before) and evictList will hold keys only

internal/cache/cache.go Show resolved Hide resolved
key string
ts time.Time
// removeOldest removes the oldest item from the cache. Has to be called with lock!
func (c *LoadingCache) removeOldest() {
Copy link
Member

Choose a reason for hiding this comment

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

this name is misleading. As far as I undesrstand it is oldes for TTL case, but not in LRU case

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oldest by creation time in case of LRC, oldest by access time in case of LRU.

Copy link
Member

Choose a reason for hiding this comment

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

well, "oldest" means an age, at least this is how I read it. In the case of LRU this is not "age" but rather "access time". Not sure what the right name here, but "oldest" is misleading for real

}

// deleteExpired deletes expired records. Has to be called with lock!
func (c *LoadingCache) deleteExpired() {
Copy link
Member

Choose a reason for hiding this comment

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

not sure what expired exactly means for LRU cache. TTL (expiresAt) shoudn't play any role in this case

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It works only if Expired is set to something less than noEvictionTTL. The function does exactly what is written here: deletes expired entries.
It won't work for the LRU cache without the expiration.

Copy link
Member

Choose a reason for hiding this comment

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

the point I'm making - LRU should not be tied to expiration in any way. Maybe it was the part of my cache implementation, but we want to simplify it and make LRU really limited by max size only and evict in LRU mode only based on max keys and the total size (indirectly). Supporting TTL in LRU mode makes all of this way too confusing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants