简体   繁体   中英

Measuring Java execution time, memory usage and CPU load for a code segment

For a particular segment of Java code, I'd like to measure:

  • Execution time (most likely thread execution time )
  • Memory usage
  • CPU load (specifically attributable to the code segment)

I'm a relative Java novice and am not familiar with how this might be achieved. I've been referred to JMX , however I'm not sure how that might be used, and JMX looks a bit 'heavy' for what I'm looking to do.

Ideally I'd like some measurement class that can be told what I would like to measure, with the option of calling a start() method prior to a code segment and a stop() method after. Relevant metrics would be logged to a file I specify.

For example:

import com.example.metricLogger;

metricLogger logger = new metricLogger();

logger.setLogPath(pathToLogFile);
logger.monitor(executionTime);
logger.monitor(memoryUsage);
logger.monitor(cpuLoad);

logger.start();

/* Code to be measured */

logger.stop();

Is there any standard/common/conventional way of achieving this in Java?

Such measurements are for one-off performance comparisons, and so I'm not looking for any in-production long-term monitoring processes.

I'm more than happy to be referred to tutorials or external examples and don't expect a full answer here. That said, if anything as simple as the above can be achieved a realistic example would go down really well.

Profiling may be an easier option since you don't require in-production stats. Profiling also doesn't require code modification. VisualVM (which ships w/ the JDK 1.6.06+) is a simple tool. If you want something more in-depth I'd go with Eclipse TPTP, Netbeans profiler, or JProfiler(pay).

If you want to write you own, consider the following:

Simple measurments like execution time can be done by "clocking" the section you're interested in:

long start = System.nanoTime(); // requires java 1.5
// Segment to monitor
double elapsedTimeInSec = (System.nanoTime() - start) * 1.0e-9;

You can use a similar technique to monitor memory via Runtime.getRuntime().*memory() methods. Keep in mind that tracking memory usage in a garbage collected environment is trickier than simple subtraction.

CPU load is hard to measure in Java, I typically stick with execution time and optimize the longer / repetitive sections

With the ThreadMXBean you can get CPU usage of individual threads and cpu time consumed rather than elapse time which may be useful.

However, its often simpler to use a profiler as this process often generates a lot of data and you need a good visualisation tool to see what is going on.

I use Yourkit as I find it easier to solve problems that other profilers I have used. I also use the builtin hprof as this can give you a different view on the profile of your application (but not as useful)

Using a Java Profiler is the best option and it will give you all the insight that you need into the code. viz Response Times, Thread CallTraces, Memory Utilisations, etc

I will suggest you JENSOR , an open source Java Profiler, for its ease-of-use and low overheads on CPU. You can download it, instrument the code and will get all the info you need about your code.

You can download it from: http://jensor.sourceforge.net /

We can measure the cpu and memory used during a specific invoked method by collecting the cpu and memory metrics during its execution.
Of course if other concurrent threads for other methods consumes memory and cpu during its execution, you are stuck. So it is a valid approach while you are able to execute a method in a isolated way.

For the CPU you can get its current value :

OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
            OperatingSystemMXBean.class); 
double processCpuLoad = osBean.getProcessCpuLoad();

For the memory you can do that :

MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
int currentHeapUsedInMo = (int) (memoryMXBean.getHeapMemoryUsage().getUsed() / 1_000_000);

About the memory measure, waiting for a major collect before executing the method improves its reliability.

For example something like that may help :

import com.google.common.testing.GcFinalization;

GcFinalization.awaitFullGc();
foo.execute(); // method to execute

GcFinalization comes from the Guava test library .

All that has few overheads. So the idea is collecting metrics (for example each second) for each invoked method you want to monitor and when the method returned, compute the max/average or any useful information for them.

I would favor AOP to do that.
Spring AOP is a simple and good way to create aspects and set pointcuts for them but you can also do it with AspectJ if you need some particular things in terms of AOP features.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM