Java memory cache

I’m looking for some ideas and maybe some specific implementation if someone knows, but I’m ready to independently code the desired cache.

I want to have a cache that caches only as many gigs as I configure. Compared to the rest of the application, part of the cache will use almost 100% of the memory, so we can generalize the used memory of the application with the cache size (+ garbage).

Are there methods to determine how much memory is being used? Or is it better to rely on soft pointers? A soft pointer and always works at the top of the jvm memory limit can be very inefficient with lots of CPU cycles to clear the memory? Can I analyze existing objects, for example myObject.getMemoryUsage() ?

LinkedHashMap has enough cache hits for my purpose, so I don’t need to code some kind of strategic caching monster, but I don’t know how to solve this problem correctly. Any ideas? I don't want OOME to fly anywhere.

What is the best rating?

+4
source share
4 answers

I would recommend using the Java Caching System . Although, if you want to roll on your own, I do not know how to get the size of objects in memory. It would be best to extend AbstractMap and wrap the values ​​in SoftReferences. Then you can set the java heap size to the maximum size you need. Although your implementation will also have to find and clear outdated data. It might be easier to just use JCS.

+1
source

SoftReference is a great idea, as they tend to be clearer right away. This means that when you get a performance hit from the GC, you also get a hit that should rebuild your cache.

You can use Instrumentation.getObjectSize () to get the small size of the object and use reflection to get the deep size. However, doing this is relatively expensive, and not something you want to do very often.

Why can't you limit the size to multiple objects? In fact, I would start with the simplest cache you can, and just add what you really need.

LRU cache in Java.

EDIT: One way to keep track of how much memory you are using is to serialize the value and save it as a byte []. This can give you pretty precise control, but it can slow down your decision by 1000 times. (Nothing comes for free;)

+2
source

The problem with SoftReferences is that they give more work to the garbage collector. Despite the fact that it does not meet your requirements, HBase has a very interesting strategy to prevent the use of the cache in pauses of garbage collection: they store the cache in their own memory:

A good start to your use case is to save all your data to disk. This may seem naive, but thanks to the I / O cache, the often-received data will be in memory. I highly recommend reading these architectural notes from the varnish caching system:

+1
source

The best practice that I find is delegating the caching function outside of Java, if possible. Java may be good at managing memory, but you should use something more than a simple LRU cache in a dedicated cache system.

There is a lot of cost with GC when it enters.

EHCache is one of the most popular that I know of. The Java Caching System from another answer is also good.

However, I usually unload this work into a basic function (usually this is the JPA save level by the application server, I let it be processed there, so I do not need to deal with it at the application level).

If you cache other data such as web requests, http://hc.apache.org/httpclient-3.x/ is also another good candidate.

However, remember that you also have a “file system”, there is absolutely nothing wrong with writing the file system data that you received. I used this technique several times to fix errors due to misuse of ByteArrayOutputStreams

0
source

All Articles