Reputation: 13038
I am using guava's cache on server side of my gwt-webapp. But to configure the cache properly i need to know some "telemetry". First I need to know how much memory one cache entry takes. So far i tried jconsole and visualvm. The problem is, I don't know where to look at. I looked for ConcurrencyHashMap and its entries, but can't find the correct number of instances.
So what is a good and probably easy way to profile a (guava) cache?
(at the moment i am not ready to pay for a tool to just get an approximation/average of size of cach (entry))
summarization of state of discussion: Aaron Digulla suggest to use weak references and let Java do the Job of managing memory. But in an previous question the people suggest to "tune, monitor, tune" the cache because of performance issues on using weak references.
update ok my question was probably misguiding - i don't want to know something about the cache or its overhead. i want to know how big is an instance of a given object - to configure a cache (in this case guava). the first question i must answer is: Could i get all instances in memory (100% hit rate) or how much memory this will take. If this is possible no cache configuration is necessary. if all object will take too much memory i must think about configuration. My hope is there is a tool that could say something about an average memory footprint of objects.
Upvotes: 4
Views: 6535
Reputation: 12692
It's not really an external tool, but you could use something like memory-measurer to log the size of your entries. Something like:
Cache cache = ...
// copy the entries to avoid measuring the footprint of the "EntrySet view"
List<Map.Entry<K, V>> entries = ImmutableList.copyOf(cache.asMap().entrySet());
long memory = MemoryMeasurer.measureBytes(entries);
logger.trace("Size of %s entries : %s bytes", entries.size(), memory);
You could log this every few minutes and then analyze the data.
I think there were discussions of providing better profiling tools to simplify Guava cache tuning. The idea of a "self-tuning" Cache was also brought up. Can't seem to find the discussion thread where I read that, though.
Upvotes: 2
Reputation: 48090
See this question for a solution with JProfiler.
JProfiler 8 will have a dedicated Guava probe. Disclaimer: My company develops JProfiler.
Upvotes: 2
Reputation: 328770
The correct solution is to call the stats()
method. The amount of memory the cache uses is pretty much irrelevant, especially when you look at memory prices. From a ROI point of view: If you spend more than a few hours on trying to memory optimize your cache, installing another 4GB of RAM would have been cheaper.
Also it's not easy to determine the "size of an entry". Depending on what values you put into the cache, the size of a single entry can vary. You can try to look up the instances of LocalCache.LocalLoadingCache
(if you use a CacheLoader
in build()
) or LocalCache.LocalManualCache
in a heap dump.
That should give you an average of the size of the instance but it won't be much help: The size isn't "recursive", so it doesn't take references into account. The problem with including references is where to stop.
For example, each class has a reference to the classloader. Many classloaders keep references to all the classes they have loaded. If that was included, the size of your instances would be way off.
YourKit is pretty good at this kind of analysis but as I said above, it's usually not worth it.
Upvotes: 7