1

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

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 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?

1 Answer 1

4

the problem is that lines:

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;
PREV_TOTAL = TOTAL;
PREV_IDLE = IDLE;

as you can see PREV_IDLE and PREV_TOTAL are shared between all cores; probably you want to keep them core-specific, so you should load that values before using them.

a nice idea would be instead of

PREV_TOTAL = TOTAL;
PREV_IDLE = IDLE;

save them into usageData2

Sign up to request clarification or add additional context in comments.

3 Comments

Yes, this is exactly the problem. How I can solve it?
see the edit for a suggestion of how store the value core-dependently. You are already saving "DIFF_USAGE" by core, so i assume you have all the instrument and suggestion to write the code by yourself. just pay attention at the first iteration when you still does not have any "TOTAL" and "IDLE" value in the map, NullException may rise if not handled properly
Could you please paste the complete example?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.