Pergunta

So I'm trying to write an app that measures CPU usage (ie, the time CPU is working vs the time it isn't). I've done some research, but unfortunately there are a bunch of different opinions on how it should be done.

These different solutions include, but aren't limited to: Get Memory Usage in Android
and
http://juliano.info/en/Blog:Memory_Leak/Understanding_the_Linux_load_average

I've tried writing some code myself, that I though might do the trick, because the links above don't take into consideration when the core is off (or do they?)

    long[][] cpuUseVal = {{2147483647, 0} , {2147483647, 0} , {2147483647, 0} , 
        {2147483647, 0} , {2147483647, 0}};

    public float[] readCPUUsage(int coreNum) {
    int j=1;
    String[] entries;  //Array to hold entries in the /proc/stat file
    int cpu_work;
    float percents[] = new float[5];
    Calendar c = Calendar.getInstance();

    // Write the dataPackage
    long currentTime = c.getTime().getTime();

        for (int i = 0; i <= coreNum; i++){
    try {     
            //Point the app to the file where CPU values are located
            RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
            String load = reader.readLine();
            while (j <= i){
                load = reader.readLine();
                j++;
            }
            //Reset j for use later in the loop
            j=1; 

            entries = load.split("[ ]+");

            //Pull the CPU working time from the file
            cpu_work = Integer.parseInt(entries[1]) + Integer.parseInt(entries[2]) + Integer.parseInt(entries[3])
                      + Integer.parseInt(entries[6]) + Integer.parseInt(entries[6]) + Integer.parseInt(entries[7]);
            reader.close();

            percents[i] = (float)(cpu_work - cpuUseVal[i][1]) / (currentTime - cpuUseVal[i][0]);

            cpuUseVal[i][0] = currentTime;
            cpuUseVal[i][1] = cpu_work;

    //In case of an error, print a stack trace   
    } catch (IOException ex) {
        ex.printStackTrace();
      }
    }
    //Return the array holding the usage values for the CPU, and all cores
    return percents;
}

So here is the idea of the code I wrote...I have a global array with some dummy values that should return negative percentages the first time the function is run. The values are being stored in a database, so I would know to disregard anything negative. Anyway, the function runs, getting values of time the cpu is doing certain things, and comparing it to the last time the function is run (with the help of the global array). These values are divided by the amount of time that has passed between the function runs (with the help of the calendar)

I've downloaded some of the existing cpu usage monitors and compared them to values I get from my app, and mine are never even close to what they get. Can someone explain what I'm doing wrong?

Thanks to some help I have changed my function to look like the following, hope this helps others who have this question

    // Function to read values from /proc/stat and do computations to compute CPU %
public float[] readCPUUsage(int coreNum) {
    int j = 1;
    String[] entries; 
    int cpu_total;
    int cpu_work;
    float percents[] = new float[5];

    for (int i = 0; i <= coreNum; i++) {
        try {
            // Point the app to the file where CPU values are located
            RandomAccessFile reader = new RandomAccessFile("/proc/stat","r");
            String load = reader.readLine();
            // Loop to read down to the line that corresponds to the core
            // whose values we are trying to read
            while (j <= i) {
                load = reader.readLine();
                j++;
            }
            // Reset j for use later in the loop
            j = 1;
            // Break the line into separate array elements. The end of each
            // element is determined by any number of spaces
            entries = load.split("[ ]+");

            // Pull the CPU total time on and "working time" from the file
            cpu_total = Integer.parseInt(entries[1])
                    + Integer.parseInt(entries[2])
                    + Integer.parseInt(entries[3])
                    + Integer.parseInt(entries[4])
                    + Integer.parseInt(entries[5])
                    + Integer.parseInt(entries[6])
                    + Integer.parseInt(entries[7]);
            cpu_work = Integer.parseInt(entries[1])
                    + Integer.parseInt(entries[2])
                    + Integer.parseInt(entries[3])
                    + Integer.parseInt(entries[6])
                    + Integer.parseInt(entries[7]);
            reader.close();

            //If it was off the whole time, say 0
            if ((cpu_total - cpuUseVal[i][0]) == 0)
                percents[i] = 0;
            //If it was on for any amount of time, compute the %
            else
                percents[i] = (float) (cpu_work - cpuUseVal[i][1])
                        / (cpu_total - cpuUseVal[i][0]);

            //Save the values measured for future comparison
            cpuUseVal[i][0] = cpu_total;
            cpuUseVal[i][1] = cpu_work;

            // In case of an error, print a stack trace
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    // Return the array holding the usage values for the CPU, and all cores
    return percents;
}
Foi útil?

Solução

Apps don't measure CPU usage, the kernel does by interrupting the process 100 times per second (or some other frequency depending on how the kernel is tuned) and incrementing a counter which corresponds to what it was doing when interrupted.

If in the process => increment the user counter.

If in the kernel => increment the system counter

If waiting for disk or network or a device => increment the waiting for IO

Otherwise increment the idle counter.

The uptime is determined by the decaying average length of the run queue i.e. how many threads are waiting to run. The first number is the average length over the last minute. You can get the load average via JMX.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top