0

this LRU cache implementation is based on Java linkedHashMap

https://codereview.stackexchange.com/questions/80247/lru-cache-design-using-linkedhashmap

with the eviction condition in removeEldestEntry defined as size() > MAX_ENTRIES. I would rather need a byte-oriented eviction mechanism, e.g. bytesCached > MAX_SIZE (MAX_SIZE is the cache physical dimension).

How to evict entries if, for example, bytesCached >100MB rather than size()>50?

Many thanks.

.m

Community
  • 1
  • 1
  • 1
    By size do you mean Object's size or reference size? Reference size is constant and object size depends on what it stores. – Gurwinder Singh Dec 11 '16 at 14:47
  • I mean the Object’s size. removeEldestEntry() can be changed to “return current_size > MAX_SIZE”, but linkedHashMap’s constructor takes MAX_ENTRIES and a sequence of put() of small files can fill all available entries even if MAX_SIZE is not reached – Marco Meoni Dec 11 '16 at 17:42

1 Answers1

0

There can be short and long answer.

The short answer is that you can theoretically count number of bytes occupied by each object stored in cache and calculate sum of them to know when it is the time to evict objects.

The longer answer is that it is not so simple. Indeed imagine that you have class like this:

class Simple {
    private int n;
    private byte b;
}

How much memory is needed to store instance of this class? Let's say it is 4 bytes for int and yet another byte for byte, so 5 bytes. We do not count the memory needed to store reference to object itself.

This case is simple. But what about the following:

class Simple2 {
    private int n;
    private byte b;
    private String s;
}

How much memory do you need now? 4+5+s.length*2? Probably this is correct. But String is class and therefore s is a reference. This reference may be reused in other object including object that is stored in the same cache. Do you want to count it twice or not? I do not know.

Let's say for simplicity that you want to count whole memory occupied by object. It means that you should go through the object recursively and calculate the memory occupied by its members. It is complicated and very performance expensive process.

Fortunately you can use other technique. Java instrumentation API allows to estimate number of bytes occupied by object. Moreover there is a project http://sizeof.sourceforge.net/ that implements this functionality and provides simple API for you.

Other possibility is to serialize object if it implements Serializable and then check the size if serilized object. It is even more expensive and requires that your class must implement Serializable. From other hand it does not need any 3rd party dependency.

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • I agree with your short answer, in fact each entry (a filename) comes with a filesize. Every time a put(filename, filesize) or get(filename) occur, bytesCached can be updated. From Javadoc, removeEldestEntry is invoked by put(filename, filesize) after inserting a new entry and returns true if the map should remove its eldest entry. I can change the eviction condition into “return current_size > MAX_SIZE”, but unfortunately the constructor wants MAX_ENTRIES and the cache can run out of entries BEFORE its space is actually full (because caching lots of small files) – Marco Meoni Dec 11 '16 at 17:38