Controlling memory size of DynaCache

One of the common problems with using caching frameworks is how do you control the size of the memory taken by the cache. Most of the caches allow you to control number of entries that should be cached, but not the maximum memory size of the cache. So it might happen that your cache will grow too big and cause memory issue for your application/application server.

Starting with WebSphere Application Server 7.0, you can control what is the maximum memory that your cache instance can take. I wanted to create cache instance and set its size to 10MB and start putting objects in the cache and make sure that the cache does not grow above 10MB. YOu can download the sample application from here

First i went into the WAS Admin Console and i did create a new cache instance SampleMemInstance and bound it at services/cache/samplememcache JNDI location like this,



As you can see i did configure maximum number of entries to 20k and maximum mem size to 10MB

Then i did create a new Web SampleDynaCacheMemSize web application, which has a servlet that takes number of entries that should be put in cache as argument and starts adding those entries in cache like this


package com.webspherenotes.dynacache;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ibm.websphere.command.CommandException;

/**
* Servlet implementation class SampleDynaCacheMemSize
*/
public class SampleDynaCacheMemSize extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
int startIndex = Integer.parseInt(request.getParameter("startIndex"));
int number = Integer.parseInt(request.getParameter("number"));
for(int i = startIndex ; i < startIndex + number ; i++ ){
System.out.println("Putting object in cache for key " + i);
SampleMemObject sampleMemObject = new SampleMemObject(i);
try {
sampleMemObject.execute();
} catch (CommandException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}


Then the last piece is to create a SampleMemObject CacheableCommand object like this


package com.webspherenotes.dynacache;

import com.ibm.websphere.cache.Sizeable;
import com.ibm.websphere.command.CacheableCommandImpl;


public class SampleMemObject extends CacheableCommandImpl implements Sizeable{
/**
*
*/
private static final long serialVersionUID = 1027837849378068229L;
private int cacheKey;

public SampleMemObject(int cacheKey){
this.cacheKey = cacheKey;
}

@Override
public long getObjectSize() {
return 1048576;
}

@Override
public boolean isReadyToCallExecute() {
return true;
}

@Override
public void performExecute() throws Exception {
System.out.println("Inside SampleMemObject.performExecute()");
}

public int getCacheKey() {
return cacheKey;
}

public void setCacheKey(int cacheKey) {
this.cacheKey = cacheKey;
}

}


If you want to control size of memory then you should implement Sizeable interface in your Command object and implement getObjectSize() method, this method returns a long value with size of object, in my case i am returning a value which is equal to 1 MB.

After deploying the code i did execute the servlet like this http://localhost:9080/SampleDynaCacheMemSize/SampleDynaCacheMemSize?startIndex=0&number=11, and asked it to put 11 entries in cache at that time i could see that following message is being return to the SystemOut.log because memory size is full, the message wording is wrong it should have said memory size is reached.


[2/14/11 6:11:49:718 PST] 00000018 Cache A DYNA1070I: Cache instance "services/cache/samplememcache" is full and has reached the maximum configured size of 200000 entries. Space on the JVM heap for new entries will now be made by evicting existing cache entries using the LRU algorithm. Please consider enabling the disk offload feature for the cache instance to prevent the discard of cache entries from memory.

1 comment:

Jose said...

How does the CacheableCommand know to use the new cache instance you created? "services/cache/samplememcache"