문제

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.

도움이 되었습니까?

해결책

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.

다른 팁

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top