samedi 28 février 2015

Get CPU load per core using Java



I'm using this code to get CPU load from /proc/stat using Java code:



private static long PREV_IDLE; //CPU Idle time
private static long PREV_TOTAL; //CPU Total time
private static final int CONSERVATIVE = 0;
private static final int AVERAGE = 1;
private static final int OPTIMISTIC = 2;

public static float getCPUProcOrig() throws Exception
{
BufferedReader cpuReader = null;
try
{
cpuReader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/stat")));
String cpuLine = cpuReader.readLine();
if (cpuLine == null)
{
throw new Exception("/proc/stat didn't work well");
}
else
{
String[] CPU = cpuLine.split("\\s+");

long IDLE = Long.parseLong(CPU[4]);//Get the idle CPU time.
long TOTAL = Long.parseLong(CPU[1]) + Long.parseLong(CPU[2]) + Long.parseLong(CPU[3]) + Long.parseLong(CPU[4]);
// System.out.println("IDLE : " + IDLE);

long DIFF_IDLE = IDLE - PREV_IDLE;
long DIFF_TOTAL = TOTAL - PREV_TOTAL;
long DIFF_USAGE = DIFF_TOTAL == 0 ? 0 : (1000 * (DIFF_TOTAL - DIFF_IDLE) / DIFF_TOTAL + 5) / 10;
// System.out.println("CPU: " + DIFF_USAGE + "%");

PREV_TOTAL = TOTAL;
PREV_IDLE = IDLE;
return (float) DIFF_USAGE;
}
}
catch (Exception e)
{
throw e; // It's not desirable to handle the exception here
}
finally
{
if (cpuReader != null)
try
{
cpuReader.close();
}
catch (IOException e)
{
// Do nothing
}
}
}


Unfortunately this code works well but for average CPU load. I would like to list all cores load separately. I tried to extend the code:



private static long PREV_IDLE; //CPU Idle time
private static long PREV_TOTAL; //CPU Total time
private static final int CONSERVATIVE = 0;
private static final int AVERAGE = 1;
private static final int OPTIMISTIC = 2;

public HashMap<String, HashMap<String, Float>> getCPUProc() throws Exception
{
BufferedReader cpuReader = null;
HashMap<String, HashMap<String, Float>> usageData = new HashMap<>();

try
{
String line;
cpuReader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/stat")));
while ((line = cpuReader.readLine()) != null)
{
String[] CPU = line.split("\\s+");
if (CPU[0].startsWith("cpu"))
{
String cpuName = String.valueOf(CPU[0]);//Get the cpu number.
long IDLE = Long.parseLong(CPU[4]);//Get the idle CPU time.
long TOTAL = Long.parseLong(CPU[1]) + Long.parseLong(CPU[2]) + Long.parseLong(CPU[3]) + Long.parseLong(CPU[4]);
// System.out.println("IDLE : " + IDLE);

long DIFF_IDLE = IDLE - PREV_IDLE;
long DIFF_TOTAL = TOTAL - PREV_TOTAL;
long DIFF_USAGE = DIFF_TOTAL == 0 ? 0 : (1000 * (DIFF_TOTAL - DIFF_IDLE) / DIFF_TOTAL + 5) / 10;
// System.out.println("CPU: " + DIFF_USAGE + "%");

PREV_TOTAL = TOTAL;
PREV_IDLE = IDLE;

HashMap<String, Float> usageData2 = new HashMap<>();
usageData2.put("cpu", (float) DIFF_USAGE);

usageData.put(cpuName, usageData2);
}

// return (float) DIFF_USAGE;
}
}
catch (IOException | NumberFormatException e)
{
throw e; // It's not desirable to handle the exception here
}
finally
{
if (cpuReader != null)
try
{
cpuReader.close();
}
catch (IOException e)
{
// Do nothing
}
}
return usageData;
}


As you can see from the first code there are several static variables which are used to calculate the CPU load. When I try to read all lines from /proc/stat these static variables are not used properly and data between the cores is messed up and the result is not accurate.


Can you help me to read the load properly? I'm out of ideas. How I can fix the code?




Aucun commentaire:

Enregistrer un commentaire