We added some choice Cache.getOrElse() statements in our Play 2.2.2 application to store some intermediate products of some rather CPU intensive calculations. Seemed like an easy win! Several of these are rather complex case classes and we noticed that after implementing this we observed two things (a) the memory usage of the JVM goes up substantially (b) we get a bunch of warnings like the following:
[warn] 20:01:57 net.sf.ehcache.pool.sizeof.SizeOf: The configured limit of 100,000 object references was reached while attempting to calculate the size of the object graph.
This can be avoided by adding stop points with @IgnoreSizeOf annotations. Since the CacheManger or Cache <sizeOfPolicy> elements maxDepthExceededBehavior is set to "abort", the sizing operation has stopped and the reported cache size is not accurate.
If performance degradation is NOT an issue at the configured limit, raise the limit value using the CacheManager or Cache <sizeOfPolicy> elements maxDepth attribute.
For more information, see the Ehcache configuration documentation.
My initial thinking was that because we are storing these complex classes, that the Cache was sucking in other parts of the object that were required to "fully reconstitute" the object once returned out of the cache. So we created some more simple objects - stripping companion objects, and re-typing any fields in the classes that are not Strings or Ints. But even really simple maps of strings seem to be storing a lot of objects (and therefore I presume a lot of memory used) in the Cache.
An example that stores a map of stringsfrom a redis object:
val value = Cache.getOrElse[Map[String,String]]("Cache:PicturesForFolios", expiration = 840000){
client.hgetAll("Bookmarks:Photos")
}
This map of redis results we are storing has precisely 256 key -> values and the jedis library returns this as a Map[String,String]. So why would this result in that warning of > 100000 objects being calculated for the cache? Performance-wise this is a huge problem because the calculation of the cache size takes a long time and I'm not sure setting the cache to ignore calculation is a wise choice when ehcache is being used extensively!
What am I not getting about ehcache and how this works? Do I need to do my own serialization of any object I want to put in the cache so that everything is forced to a single key -> value???