Question

I'm trying to measure the memory usage of my own datastructure in my Tomcat Java EE application at various levels of usage.

To measure the memory usage I have tried two strategies:

  1. Runtime freeMemory and totalMemory:

    System.gc(); //about 20 times
    long start = Runtime.getRuntime().freeMemory();
    
    useMyDataStructure();
    
    long end = Runtime.getRuntime().freeMemory();
    
    System.out.println(start - end);
    
  2. MemoryPoolMXBean.getPeakUsage():

    long before = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    List<MemoryPoolMXBean> memorymxbeans = ManagementFactory.getMemoryPoolMXBeans();
    for(MemoryPoolMXBean memorybean: memorymxbeans){
        memorybean.resetPeakUsage();
    }
    
    useMyDataStructure();
    
    for(MemoryPoolMXBean memorybean: memorymxbeans){
        MemoryUsage peak = memorybean.getPeakUsage();
        System.out.println(memorybean.getName() + ": " + (peak.getUsed() - before));
    }
    

Method 1 does not output reliable data at all. The data is useless.

Method 2 outputs negative values. Besides it's getName() tells me it's outputting Code Cache, PS Eden Space, PS Survivor Space and PS Old Gen seperately.

How can I acquire somewhat consistent memory usage numbers before and after my useMyDataStructure() call in Java? I do not wish to use VirtualVM, I prefer to catch the number in a long object and write it to file myself.

Thanks in advance.


edit 1:

useMyDatastructure in the above examples was an attempt to simplify the code. What's really there:

        int key = generateKey();
        MyOwnObject obj = makeAnObject();
        MyContainerClass.getSingleton().addToHashMap(key, obj);

So in essence I'm really trying to measure how much memory the HashMap<Integer, MyOwnObject> in MyContainerClass takes. I will use this memory measurement to perform an experiment where I fill up both the HashMap and MyOwnObject instances.

Was it helpful?

Solution

1st of all sizing objects in java is non-trivial (as explained very well here).

if you wish to know the size of a particular object, there are at least 2 open source libraries that will do the math for you - java.sizeof and javabi-sizeof

now, as for your specific test - System.gc() is mostly ignored by modern (hotspot) jvms, no matter how many times you call it. also, is it possible your useMyDataStructure() method does not retain a reference to the object(s) it creates? in that case measuring free memory after calling it is no good as any allocated Objects might have been cleared out.

OTHER TIPS

You could try https://github.com/jbellis/jamm, this works great for me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top