-
Notifications
You must be signed in to change notification settings - Fork 36
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
Limit the cache based on arbitrary measures #38
Comments
This is a neat idea. I need to ponder this further, but I think I'm in favor of going the |
@apasel422 The situation is a bit different, though, since the measure can be changed through plain old mutability as opposed to just interior mutability like I wonder if |
I do like the idea of a I was also thinking it could be Is there a way to avoid storing a duplicate |
I have a patch for this mostly done, with the exception of the |
This commit allows creating LruCaches that are limited in size by something other than a count of entries. It does this by providing a new trait, `Meter`, where implementations of the trait provide a `measure` method to do the measurement. The default behavior of measuring by the count of entries is provided by a `Count` type. Due to difficulties with mutating entries making it possible to change an item's measure, the `get_mut` and `iter_mut` methods are provided only on LruCaches using `Count` for sizing. A bit of optimization is provided for the default case--to avoid having to redundantly store the item count the `Meter` trait allows implementations to provide a type for storing the measurement, and the `Count` implementation uses `()`. The `CountableMeter` trait allows `LruCache` to work with this or any `Meter` implementation that uses `usize` for measurement. Finally an optional feature is added, `heapsize`, which uses the heapsize crate to provide HeapSizeOf, a measurement based on the heap memory usage of values stored in the cache.
This commit allows creating LruCaches that are limited in size by something other than a count of entries. It does this by providing a new trait, `Meter`, where implementations of the trait provide a `measure` method to do the measurement. The default behavior of measuring by the count of entries is provided by a `Count` type. Due to difficulties with mutating entries making it possible to change an item's measure, the `get_mut` and `iter_mut` methods are provided only on LruCaches using `Count` for sizing. A bit of optimization is provided for the default case--to avoid having to redundantly store the item count the `Meter` trait allows implementations to provide a type for storing the measurement, and the `Count` implementation uses `()`. The `CountableMeter` trait allows `LruCache` to work with this or any `Meter` implementation that uses `usize` for measurement. Finally an optional feature is added, `heapsize`, which uses the heapsize crate to provide HeapSizeOf, a measurement based on the heap memory usage of values stored in the cache.
Motivation:
My use-case for
lru-cache
involves inspecting items' heap size. Rather than hack it in, I think it would be beneficial to make the cache adaptable to whatever limit needs to be imposed.You might have a set of heterogeneous items, each using a different amount of allocation on the heap. Maybe a more general
Meter
trait might help:The default
Meter
could be aCount
:Here's an implementation that would use the
HeapSizeOf
trait (I'd recommend this one for inclusion under a feature gate as it's generally useful.)When you add or remove an item, you add or subtract
meter.measure(&item)
from the maximum respectively. If the metered total exceeds the maximum while adding an item, other items must be removed in a loop until the total falls below the limit.Caveats:
get_mut
or interior mutability could allow items to be altered such that their measure at insertion time differs from their measure at removal. We could add aUniformMeter<T>
which takes no reference to individual items when measuring -- indicating that the measurement is unrelated to item size.get_mut
might only be implemented when the meter is uniform, whilefn get(&mut self, key: &Q) -> Option<&T>
would serve as an alternative implemented for all caches. This doesn't solve the interior mutability issue, but that can be addressed the same way as inHashMap
: documentation specifying that it's a logic error to modify the value such that its measure would be altered.insert
can remove multiple items -- how do we return each of them to the caller efficiently? (maybe an iterator?)Alternatively:
get_mut
and adjust the total correspondingly. The issue here is that it would need to be done through aCacheHandle<'a, T: 'a>
which contains that logic in its destructor. This would break backwards compatibility, and would need to handle returning displaced items if the size grows.Looking forward to your comments and naming suggestions below.
The text was updated successfully, but these errors were encountered: