How to calculate CPU usage of each Java thread and not just the whole process

Many times we face high CPU usage issues in our production servers. We can use manual ways to find out the threads which are consuming the maximum CPU and hence identify the leaking code. But how to programitacally find the CPU usage per thread. We can use ManagementFactory class of JDK to calculate CPU usage per thread.
This code first stores the initial CPU usage of each thread, sleeps for some sample time, again finds the current CPU usage of all threads and then calculates the difference and hence CPU usage per thread. We also divide the CPU usage by the number of cores present in the system
In this code I have also created two dummy threads which are intended to consume high CPU usage. Output of this code on my sytem was :

{1=0.0, 2=0.0, 3=0.0, 4=0.0, 5=0.0, 6=0.0, 7=0.0, 8=0.0, 13=12.947277, 14=10.7796335}

So thread 13 and 14, consumed maximum CPU. They correspond to 2 dummy threads.

package MemoryCpu;
 
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.HashMap;
import java.util.Map;
 
public class CpuPerThread {
	private int sampleTime = 20000;
	private ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
	private RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
	private OperatingSystemMXBean osMxBean = ManagementFactory
			.getOperatingSystemMXBean();
	private Map<Long, Long> threadInitialCPU = new HashMap<Long, Long>();
	private Map<Long, Float> threadCPUUsage = new HashMap<Long, Float>();
	private long initialUptime = runtimeMxBean.getUptime();
 
	public static void main(String[] args) {
 
		new Thread("Dummy thread"){
			public void run(){
				int i = 0;
				while(i++<10000000)
				System.out.println(i);
			}
		}.start();
 
		new Thread("Dummy thread 2"){
			public void run(){
				int i = 0;
				while(i++<10000000)
				System.out.println(i);
			}
		}.start();
		new CpuPerThread().measure();
	}
 
	private void measure() {
 
		ThreadInfo[] threadInfos = threadMxBean.dumpAllThreads(false, false);
		for (ThreadInfo info : threadInfos) {
			threadInitialCPU.put(info.getThreadId(),
					threadMxBean.getThreadCpuTime(info.getThreadId()));
		}
 
		try {
			Thread.sleep(sampleTime);
		} catch (InterruptedException e) {
		}
 
		long upTime = runtimeMxBean.getUptime();
 
		Map<Long, Long> threadCurrentCPU = new HashMap<Long, Long>();
		threadInfos = threadMxBean.dumpAllThreads(false, false);
		for (ThreadInfo info : threadInfos) {
			threadCurrentCPU.put(info.getThreadId(),
					threadMxBean.getThreadCpuTime(info.getThreadId()));
		}
 
		// CPU over all processes
		int nrCPUs = osMxBean.getAvailableProcessors();
		// total CPU: CPU % can be more than 100% (devided over multiple cpus)
		//long nrCPUs = 1;
		// elapsedTime is in ms.
		long elapsedTime = (upTime - initialUptime);
		for (ThreadInfo info : threadInfos) {
			// elapsedCpu is in ns
			Long initialCPU = threadInitialCPU.get(info.getThreadId());
			if (initialCPU != null) {
				long elapsedCpu = threadCurrentCPU.get(info.getThreadId())
						- initialCPU;
				float cpuUsage = elapsedCpu * 100/ (elapsedTime * 1000000F * nrCPUs);
				threadCPUUsage.put(info.getThreadId(), cpuUsage);
			}
		}
 
		// threadCPUUsage contains cpu % per thread
		System.out.println(threadCPUUsage);
		// You can use osMxBean.getThreadInfo(theadId) to get information on
		// every thread reported in threadCPUUsage and analyze the most CPU
		// intentive threads
 
	}
}

Uday Ogra

Connect with me at http://facebook.com/tendulkarogra and lets have some healthy discussion :)

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *