Reputation: 129373
I'm trying to memory-optimize my server that keeps running into OOM.
Most of the objects (by count) in the server take the following form:
Important caveat: 95% of such hashmaps would ONLY EVER have one key; and I know whether that's the case when creating the hashmap.
There are millions of these hashmaps.
I already asked a separate question about optimizing those hashmaps memory wise, and someone in a comment suggested that perhaps re-engineering my whole data structure would be better since even with initial size of "1" HashMaps still take up extra memory.
As such, my question is; is there a better Java data structure I can implement which can store the same exact data with better memory efficiency?
NOTE: I need to be able to look up whether a specific value is present as a key; therefore I have considered but rejected storing the data in an list of quintuples of [string_value, int, boolean, boolean].
Upvotes: 2
Views: 1097
Reputation: 18793
Expose the less specific Map
interface to the user instead of HashMap
, this given you the freedom to use hash maps or singleton maps depending on the case.
Memory efficient singleton maps can be created via Collections.singletonMap()
: https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#singletonMap(K,%20V)
SingletonMap
seems to be implemented as an object with just two fields and some cache: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collections.java#Collections.SingletonMap
p.s. You could have something even more compact for your special case by collapsing the map and value into a single instance like this:
public final class SingletonAttributeMap extends Attribute implements Map<String,Attribute> {
private final String key;
public Attribute get(String key) {
return this.key.equals(key) ? this : null;
}
....
}
p.p.s Is there a maximum size for the integers in the attributes? You might be able to do tricks like this (whether this actually saves memory will depend on padding / alignment, see What is the memory consumption of an object in Java?):
class Attribute {
private int value;
boolean getBoolean1() {
return (value & 1) != 0;
}
boolean getBoolean2() {
return (value & 2) != 0;
}
int getInt() {
return value >> 2;
}
void setBoolean1(boolean b) {
value = (value & ~1) | (b ? 1 : 0);
}
void setInt(int i) {
value = (value & ~3) | (i << 2);
}
...
Upvotes: 2
Reputation: 308743
Each object is a HashMap? Not a very good abstraction. I'd prefer composition: create an object that HAS-A HashMap and provides a clear API. Make it Comparable and implement hashCode and equals.
I would suggest that you follow the Flyweight pattern if lots of those are repeated.
If the objects are immutable and read-only this will be a perfectly good optimization.
Have a Factory object to create instances and maintain a List of unique ones. If someone asks for one that's already in the List return the immutable copy.
You can calculate how much of a memory savings this will provide before you implement it.
Upvotes: 1