Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimize memory usage of a collection of Strings in Java

I have a large number of name - value pairs (approx 100k) that I need to store in some sort of cache (say a hash map) where the value is a string with an average of about 30k bytes in size.

Now I know for a fact that a large number of the values have exactly the same string data. In order to avoid having to allocate the identical string data several times, I would like to somehow reuse a previously allocated string thus consuming less memory. In addition this needs to be reasonably fast. i.e. scanning through all the previously allocated values one-by-one is not an option.

Any recommendations on how I could solve this problem?

like image 244
Kishnan Avatar asked Apr 07 '09 13:04

Kishnan


People also ask

How do you optimize a string in Java?

A string literal should be enclosed in double-quotes. Whenever it encounters a string literal in the programmer's code, the compiler creates a String object with its value. It is the fastest way of string creation.

How do I optimize Java memory?

The most obvious place to start tuning the memory footprint is the Java heap size. If you reduce the Java heap size, you reduce the memory footprint of the Java process by the same amount. You cannot reduce the heap size beyond a point; the heap should be large enough for all objects that are live at the same time.


1 Answers

Do not use String.intern (there have been various memory issues related to this through the years). instead, create your own cache, similar to String.intern. basically, you want a Map, where each key maps to itself. then, before caching any string, you "intern" it:

private Map<String,WeakReference<String>> myInternMap = new WeakHashMap<String,,WeakReference<String>>();
public String intern(String value) {
  synchronized(myInternMap) {
    WeakReference<String> curRef = myInternMap.get(value);
    String curValue = ((curRef != null) ? curRef.get() : null);
    if(curValue != null) {
      return curValue;
    }

    myInternMap.put(value, new WeakReference<String>(value));
    return value;
  }
}

note, you use weakreferences for the keys and values so that you don't keep references for strings which you are no longer using.

like image 195
james Avatar answered Oct 10 '22 12:10

james