Tuesday, May 8, 2012

Writing own cache in JAVA

Cache is being increasingly used for improving performance. The cache improves the performance by not getting to go to database or any other system which doesnot reside in the memory( here its JVM) again and again. The cache should store those frequently accessed data or objects in the memory itself. Here in this blog i have come up with 4 different kinds of algorithms that you can use to create a cache and store the objects in the memory. In the last part i have combined all these to form the framework which one can use in any java application.

First one is  LRU (Least Recently Used)

It says that the objects that are recently used are the one that will be kept in the cache otherwise it will be removed from the cache.

The code is shown below:

public class LRUCache  {
  private int cacheSize;
  private Map<Object,Object> cache;
  private List<Object> keyList;
  /**
   * Default constructor
   */
  public LRUCache() {
    this.cacheSize = 100;
    this.cache = new ConcurrentHashMap<Object,Object>();
    this.keyList = Collections.synchronizedList(new LinkedList<Object>());
  }
 
  /**
   * Add an object to the cache
   *
   *
   * @param key        The key of the object to be cached
   * @param value      The object to be cached
   */
  public void putObject(Object key, Object value) {
    cache.put(key, value);
    keyList.add(key);
    if (keyList.size() > cacheSize) {
      try {
        Object oldestKey = keyList.remove(0);
        cache.remove(oldestKey);
      } catch (IndexOutOfBoundsException e) {
        //ignore
      }
    }
  }
  /**
   * Get an object out of the cache.
   *
   * @param key        The key of the object to be returned
   * @return The cached object (or null)
   */
  public Object getObject(Object key) {
    Object result = cache.get(key);
    keyList.remove(key);
    if (result != null) {
      keyList.add(key);
    }
    return result;
  }
  public Object removeObject(Object key) {
    keyList.remove(key);
    return cache.remove(key);
  }
  /**
   * Flushes the cache.
   *
   *
   */
  public void flush() {
    cache.clear();
    keyList.clear();
  }
}

The second one is FIFO (First In First Out)

The code for the same algorithm is

public class FifoCache {
  private int cacheSize;
  private Map<Object,Object> cache;
  private List<Object> keyList;
  /**
   * Default constructor
   */
  public FifoCache() {
    this.cacheSize = 100;
    this.cache = new ConcurrentHashMap<Object,Object>();
    this.keyList = Collections.synchronizedList(new LinkedList<Object>());
  }

  /**
   * Add an object to the cache
   *
   *
   * @param key        The key of the object to be cached
   * @param value      The object to be cached
   */
  public void putObject(Object key, Object value) {
    cache.put(key, value);
    keyList.add(key);
    if (keyList.size() > cacheSize) {
      try {
        Object oldestKey = keyList.remove(0);
        cache.remove(oldestKey);
      } catch (IndexOutOfBoundsException e) {
        //ignore
      }
    }
  }
  /**
   * Get an object out of the cache.
   * @param key        The key of the object to be returned
   * @return The cached object (or null)
   */
  public Object getObject(Object key) {
    return cache.get(key);
  }
  public Object removeObject(Object key) {
    keyList.remove(key);
    return cache.remove(key);
  }
  /**
   * Flushes the cache.
   *
   * @param cacheModel The cache model
   */
  public void flush() {
    cache.clear();
    keyList.clear();
  }
}

Wednesday, May 2, 2012

Weak Reference vs Strong Reference vs Soft Reference in Java

One of the most neglected areas in JAVA is kind of references that we create. I was also not aware of the references untill i implemented the memory cache. I will be using it as an example to showcase the usage of references. One of the important variations in implementaion of cache is the memory cache where we define the refererence type. The benefit of having this kind of caching mechanism is that we can basically segregate the kind of objects that can be easily garbage collected and making the memory available for more important objects.

Java provides a way to create different kinds of references. These references types if used properly can be of immense use and can be a great performance booster for an application.

There are basically three kinds of references that we can create.
  1. Weak Reference
  2. Strong Reference
  3. Soft Reference.
The references are basically used to convey the message to the garbage collector.

If its a Weak reference then the object will be garbage collected if not currently in use making the memory available for the other objects. Using this kind of reference ( for key) in cache will immemsely increase the performance in the case of most popular results. But it has a downside that it will absolutely de allocate the memory.

Example:
Creating a WeakReference
reference = new WeakReference(value);

getting the value
value = ((WeakReference) ref).get();where the ref is the reference to the value.

If its a Soft reference it will reduce the likelihood of running out of memory in case the results are not currently in use and the memory is needed for other objects. However this is not the most aggresive in this regard.Hence memory still might be alloacted and unavailable for more important objects.

Example:
Creating the SoftReference
reference = new SoftReference(value);
getting the value

value = ((SoftReference) ref).get();
where the ref is the reference to the value.

In case of Strong reference the object will remain in memory untill and unless the object is not de referenced. In case of cache implementation the performance will be very good in case of particular query.

reference =

getting the valuevalue = ((StrongReference) ref).get();
where the ref is the reference to the value.
new StrongReference(value);