Reputation: 1117
What are the best options of measuring or at least somewhat accurately estimating the total memory consumption by a hash map holding custom objects?
Background:
Our system has multiple in-memory stores (ConcurrentHashMap's) that holds 1K-200K objects of different types. We'd like to periodically monitor the memory footprint of these.
Constraints/Expectations:
We cannot afford frequent GC or full iteration of these hash maps that would have negative impact on the latency. As far as I know, there's no sizeof() in java, so we are okay with estimation.
Considering these options:
Have a thread that reports the memory usage # for each hashmap by:
Upvotes: 4
Views: 2064
Reputation: 120848
First of all, there is this great article from Alexey Shipilev (a former JVM engineer at Oracle, now at Redhat) that explain that this is not that easy.
Every Object in Java has two headers, their sizes can depend on the platform or on the configuration that jvm is started with (UseCompressedOops
).
Then, there is the padding and alignment between fields and Objects them-selves (8 bytes alignment). Then, there is space that a JVM simply does not show because it can't or does have need to.
All these things make it a bit un-trivial to compute how much size will a certain Object have in heap; fortunately JOL exists. It even has lots of samples too... Here is one small example, suppose you have such a class:
static class MyValue {
private final int left;
private final String right;
public MyValue(int left, String right) {
this.left = left;
this.right = right;
}
}
And you create a HashMap
:
Map<String, MyValue> map = new HashMap<>();
System.out.println("empty map = " + GraphLayout.parseInstance(map).totalSize());
MyValue one = new MyValue(1, "one");
System.out.println("one = " + GraphLayout.parseInstance(one).totalSize());
map.put("one", one);
System.out.println("map after one = " + GraphLayout.parseInstance(map).totalSize());
MyValue two = new MyValue(1, "two");
map.put("two", two);
System.out.println("map after two = " +
GraphLayout.parseInstance(map).totalSize());
Upvotes: 3
Reputation: 8001
If my understanding is correct, you want to know the size of the concurrent HashMap. I think, the following steps may help.
Other option is use profiler like JProfiler to see the object graph and its size.
Upvotes: 1