How to really benchmark the memory usage of a Java application

隐身守侯 提交于 2019-12-04 07:56:54

I also struggled with this issue and interested to know if there is any standard way.

The best I could do was to tell JVM to do its best to gather garbage as much as possible by calling the following method after a run and before the next one:

GcFinalization.awaitFullGc();

This method is from the Guava test-lib package, which can be added as a Maven dependency as:

 <dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava-testlib</artifactId>
    <version>18.0</version>
</dependency>

The implementation looks like this:

public static void awaitFullGc() {
   final CountDownLatch finalizerRan = new CountDownLatch(1);
   WeakReference<Object> ref = new WeakReference<Object>(
      new Object() {
         @Override protected void finalize() { finalizerRan.countDown(); }
      });

   await(finalizerRan);
   awaitClear(ref);

   // Hope to catch some stragglers queued up behind our finalizable object
   System.runFinalization();
 }

This gave me very consistent results for each run and makes the CPU user time (from ThreadMXBean) very close to nano time (from System.currentTimeMills). My main concern in those measurements was running time, but the memory usage was also consistent, compared to the version without this call in between.

First, you should look at JMH to find out how a proper Java bechmarking should be done.

Calling Runtime.getRuntime().gc() is definitely a bad practice - both in real-life and as well as when benchmarking GCs. To name at least one reason, by forcing a GC cycle you are direclty penalizing a performance of any GC algorithm.

Further, you cannot compare various GC algorithms by having them execute only ~4 GC cycles. You should run a proper GC benchmark - see JMH, and you need to run at least for a considerably long time - depending on Heap size, this can be 10 minutes, or a few hours...

I think your best bet for a start is to run for a JMH-like benchmark for a long time(~30minutes), collect GC logs and process the GC logs for various statistics... at least to have some kind of reasonable comparison to start with.

I want to compare different implementations of Java programs in terms of their memory usage efficiency.

One option is to run the program with:

-Xloggc:gc.log_impl1 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

then, switch to implementation 2 and re-run with

-Xloggc:gc.log_impl2 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

Then download HPjmeter, load both files into the console and use the compare gc feature. There may be a little bit of skew in the graphs, but you'll get a pretty good idea of how the programs memory profiles differ.

I would not try to invoke the GC synthetically.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!