Monday, 9 November 2015

android CPU usage

Total CPU time:

see the code first.

public static float getProcessCpuRate()
   {
         
       float totalCpuTime1 = getTotalCpuTime();
       float processCpuTime1 = getAppCpuTime();
       try
       {
           Thread.sleep(360);
             
       }
       catch (Exception e)
       {
       }
         
       float totalCpuTime2 = getTotalCpuTime();
       float processCpuTime2 = getAppCpuTime();
         
       float cpuRate = 100 * (processCpuTime2 - processCpuTime1)
               / (totalCpuTime2 - totalCpuTime1);
         
       return cpuRate;
   }
     
   public static long getTotalCpuTime()
   // get total cpu time since the device on
       String[] cpuInfos = null;
       try
       {
           BufferedReader reader = new BufferedReader(new InputStreamReader(
                   new FileInputStream("/proc/stat")), 1000);
           String load = reader.readLine();
           reader.close();
           cpuInfos = load.split(" ");
       }
       catch (IOException ex)
       {
           ex.printStackTrace();
       }
       long totalCpu = Long.parseLong(cpuInfos[2])
               + Long.parseLong(cpuInfos[3]) + Long.parseLong(cpuInfos[4])
               + Long.parseLong(cpuInfos[6]) + Long.parseLong(cpuInfos[5])
               + Long.parseLong(cpuInfos[7]) + Long.parseLong(cpuInfos[8]);
       return totalCpu;
   }
     
   public static long getAppCpuTime()
   // get total cpu time of current app. (since the device on.)
       String[] cpuInfos = null;
       try
       {
           int pid = android.os.Process.myPid();
           BufferedReader reader = new BufferedReader(new InputStreamReader(
                   new FileInputStream("/proc/" + pid + "/stat")), 1000);
           String load = reader.readLine();
           reader.close();
           cpuInfos = load.split(" ");
       }
       catch (IOException ex)
       {
           ex.printStackTrace();
       }
       long appCpuTime = Long.parseLong(cpuInfos[13])
               + Long.parseLong(cpuInfos[14]) + Long.parseLong(cpuInfos[15])
               + Long.parseLong(cpuInfos[16]);
       return appCpuTime;
   }

Above code just gives you total cpu time.

The cpu times are read from the comand: /proc/stat  (actually is a file. you can run it on your pc after connect your android device to your pc: adb shell cat /proc/stat )

there are a lot of data here:



if you have more than one CPUs, you will get cpu0, cpu1, cpu2.... but don't worry, the first line"cpu" gives you the summary, most of time you just need to deal with it.

But what are these number?  this page gives you most of explanations: http://www.linuxhowtos.org/System/procstat.htm

The meanings of the columns are as follows, from left to right:
  • user: normal processes executing in user mode
  • nice: niced processes executing in user mode
  • system: processes executing in kernel mode
  • idle: twiddling thumbs
  • iowait: waiting for I/O to complete
  • irq: servicing interrupts
  • softirq: servicing softirqs

But this post is too old, modern linux systems have more than 7 numbers. We got 10 number, but most of time these extra numbers are 0, so you don't need worry too much for below logics.

extra numbers:

>stealstolen which is the time spent in other operating systems when running in a virtualized environment(since 2.6.11)
>guest which is the time spent running a virtual CPU for guest operating systems under the control of the Linux kernel(since 2.6.24)

I don't know the last one.... : -(   please let me know if you know.



So, to get the total cpu time, you need sum up all numbers:

totalCpuTime = user + nice + system + idle + iowait + irq + softirq + stealstolen +guest

Somebody gives this equation: totalCpuTime = user + nice + system + idle + iowait + irq + softirq  (again that because they are going to handle old systems and most of time "stealstolen" and "guest" are 0)


To get cpu usage/ cpu time of a process (an app), you can do it by the same way, but the shell command and the result are a little bit different:

adb shell cat /proc/9826/stat      (9826 is the process id of the process)


I will not explain these numbers, i believe you don't care them, you can get the total cpu time of your app by the code above.





Total CPU Usage Percentage:

you can use above methods get total cpu time and total idol time and the overall cpu usage is: idol/total, but most of time, this number is meaningless.

because what you want is current cpu usage. But cpu data are running times (every time you run cat /proc/stat, it gives your the running cpu time since the device on), all relates to time, without a period of time, we can't compute the current cpu usage percentage.

so you need a sample time:  (360 is the sample time)


private float readUsage() {
    try {
        RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
        String load = reader.readLine();

        String[] toks = load.split(" +");  // Split on one or more spaces

        long idle1 = Long.parseLong(toks[4]);
        long cpu1 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[5])
              + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);

        try {
            Thread.sleep(360);
        } catch (Exception e) {}

        reader.seek(0);
        load = reader.readLine();
        reader.close();

        toks = load.split(" +");

        long idle2 = Long.parseLong(toks[4]);
        long cpu2 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[5])
            + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);

        return (float)(cpu2 - cpu1) / ((cpu2 + idle2) - (cpu1 + idle1));

    } catch (IOException ex) {
        ex.printStackTrace();
    }

    return 0;
} 






http://stackoverflow.com/questions/3118234/get-memory-usage-in-android


http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/com/android/server/ProcessStats.java#ProcessStats.0mRelUserTime


https://android.googlesource.com/platform/frameworks/base/+/froyo/services/java/com/android/server/LoadAverageService.java



No comments:

Post a comment