Android cpu cores reported in /proc/stat
Asked Answered
C

5

2

I am developing an Android application that shows the CPU load per core and memory consumption. For CPU load I am reading /proc/stat and for memory -> /proc/meminfo. However I see that the number of CPU cores in /proc/stat is changing during subsequent reading of the file.

cpu 230599 10622 84595 1892023 8236 16 285 0 0 0 cpu0 138005 7992 58080 1738918 6407 16 278 0 0 0 intr 9136791 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9601 0 0 0 0 0 0 ....... ctxt 16904510 btime 1394641996 processes 16919 procs_running 2 procs_blocked 0 softirq 1688530 407 706934 422 1558 407 407 92978 324500 1267 559650

and after 5seconds it becomes:

cpu 230772 10623 84671 1890801 8236 16 286 0 0 0 cpu0 138104 7993 58126 1739267 6407 16 279 0 0 0 cpu1 92668 2630 26545 151534 1829 0 7 0 0 0 intr 9144729 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9601 0 0 0 0 0 0 ........ ctxt 16923744 btime 1394641996 processes 16946 procs_running 2 procs_blocked 0 softirq 1690205 407 707396 422 1558 407 407 93311 324790 1267 560240

Does it mean that cpu cores are sleeping in some cases?

Certify answered 14/3, 2014 at 12:45 Comment(0)
N
7

I know this is old, but there does not seem to be an answer for this, and I've been searching for a solution as well.

What I figured, is that if I'm recording each core named "cpu" that follows a number. and the cpus go from 0-3. And if I'm reading the cores in order. Then if .readline() of /proc/stat returns a string that does NOT contain cpu, than that core must not be working, and is offline. So, in theory, it would be at zero percent usage. So, return 0.

*** Completed answer with code, see below ***

Heres some code, in case what I said didn't make sense, mine is based on this: Get Memory Usage in Android

and here is how I found a new calculation that gave me more accurate representation of core readings: How to get total cpu usage in Linux using C++

First, here is some of my CPU function that displays a string after these loops and stuff to the user. I'm posting this so you have a better understanding of i, and what my code means

float[] coreValues = new float[10];
                //get how many cores there are from function
                int numCores = getNumCores();
                for(byte i = 0; i < numCores; i++)
                {
                    coreValues[i] = readCore(i);
                }

getNumCores can be found here, I will not be posting since I feel like the person who did should get the credit for it: How can you detect a dual-core cpu on an Android device from code?

And, lastly, here's my code, I hope it makes sense, and I offered a lot of comments.

//for multi core value
        private float readCore(int i) 
        {
            /*
             * how to calculate multicore
             * this function reads the bytes from a logging file in the android system (/proc/stat for cpu values)
             * then puts the line into a string
             * then spilts up each individual part into an array
             * then(since he know which part represents what) we are able to determine each cpu total and work
             * then combine it together to get a single float for overall cpu usage
             */
            try {
                RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
                //skip to the line we need
                for(int ii = 0; ii < i + 1; ++ii)
                {
                    reader.readLine();
                }
                String load = reader.readLine();
                
                //cores will eventually go offline, and if it does, then it is at 0% because it is not being
                //used. so we need to do check if the line we got contains cpu, if not, then this core = 0
                if(load.contains("cpu"))
                {
                String[] toks = load.split(" ");
                
                //we are recording the work being used by the user and system(work) and the total info
                //of cpu stuff (total)
                //https://mcmap.net/q/270884/-how-to-get-total-cpu-usage-in-linux-using-c/3017438#3017438

                long work1 = Long.parseLong(toks[1])+ Long.parseLong(toks[2]) + Long.parseLong(toks[3]);
                long total1 = Long.parseLong(toks[1])+ Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + 
                        Long.parseLong(toks[4]) + Long.parseLong(toks[5])
                      + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);

                try 
                {
                    //short sleep time = less accurate. But android devices typically don't have more than
                    //4 cores, and I'n my app, I run this all in a second. So, I need it a bit shorter
                    Thread.sleep(200);
                } 
                catch (Exception e) {}

                reader.seek(0);
                //skip to the line we need
                for(int ii = 0; ii < i + 1; ++ii)
                {
                    reader.readLine();
                }
                load = reader.readLine();
              //cores will eventually go offline, and if it does, then it is at 0% because it is not being
                //used. so we need to do check if the line we got contains cpu, if not, then this core = 0%
                if(load.contains("cpu"))
                {
                    reader.close();
                    toks = load.split(" ");

                    long work2 = Long.parseLong(toks[1])+ Long.parseLong(toks[2]) + Long.parseLong(toks[3]);
                    long total2 = Long.parseLong(toks[1])+ Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + 
                            Long.parseLong(toks[4]) + Long.parseLong(toks[5])
                          + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);


                    
                    //here we find the change in user work and total info, and divide by one another to get our total
                    //seems to be accurate need to test on quad core
                    //https://mcmap.net/q/270884/-how-to-get-total-cpu-usage-in-linux-using-c/3017438#3017438
                    
                    return (float)(work2 - work1) / ((total2 - total1));
                }
                else
                {
                    reader.close();
                    return 0;
                }
                
                }
                else
                {
                    reader.close();
                    return 0;
                }

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

            return 0;
        } 

And, as a last note, my readCore function will return a value of 0.0 - 1.0, you need to multiply by 100 to get a percentage.

EDIT As requested from the comments below, Android documentation: "While active, CPUs can be brought online or put offline, change clock speeds and associated voltages (possibly also affecting memory bus speeds and other system core power state), and can enter lower power idle states while in the kernel idle loop. Not only are these different CPU power states measured for the power profile, it may be necessary to avoid the power draw variance when measuring other parameters."

Link: https://source.android.com/devices/tech/power.html#

Nadaba answered 8/9, 2014 at 3:51 Comment(7)
I actually used the code from your linked SO question while I was writing this question, but my question was what does it really mean to have a cpu core missing and showing up now and then? Is it sleeping, shutdown(is that possible) or something else?Certify
From my research I've deducted that it has gone offline when it is missing. Which means android "sleeps" it so that you can save battery and it's not always running. So, since it's not running, it would not being used. So, in theory it's usage is 0%Nadaba
My only problem now, is that my cpu cores are always showing 100%, because the idle value stays the same android not change...Nadaba
Yo dude, I updated my answer below. I know it's 5 months late on an answer, but I just wanted to make sure we finished it haha. I hope it helps you out in the future!Nadaba
This looks nice, but I will take a deeper look some other time because lately I am busy with something completely different. And if in the meantime you could add link to the official documentation that states that Android "shuts down" cores to save battery, then this will be the accepted answer for sure.Certify
Found some official documentation to prove what I'm saying. A lot of third-party sources claim this too!Nadaba
Look at my answer. It's completely based on your, but before returning you should add a check, in order to avoid dividing by 0...Developing
D
1

Even if the accepted answer was given a few months after the question, it was very useful to me. Hopefully my suggestion will be useful to anyone else reading this question in the future.
The answer of @Torch2424 was very good but is missing a check: as you stated, sometimes Android doesn't use all the CPUs; I tried your code on a 4-core tablet and indeed I see that most of the time 2 CPUs are not used at all or not changing that often, therefore the relative lines of /proc/stat file are exactly the same. This means that (total2 - total1) equals to 0 and then you try to divide by 0, whose result is NaN.
This is actually my working code for the readCore() function:

// for multi core value
private float readCore(int i) {
    /*
     * how to calculate multicore this function reads the bytes from a
     * logging file in the android system (/proc/stat for cpu values) then
     * puts the line into a string then spilts up each individual part into
     * an array then(since he know which part represents what) we are able
     * to determine each cpu total and work then combine it together to get
     * a single float for overall cpu usage
     */
    try {
        RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
        // skip to the line we need
        for (int ii = 0; ii < i + 1; ++ii) {
            String line = reader.readLine();            
        }
        String load = reader.readLine();

        // cores will eventually go offline, and if it does, then it is at
        // 0% because it is not being
        // used. so we need to do check if the line we got contains cpu, if
        // not, then this core = 0
        if (load.contains("cpu")) {
            String[] toks = load.split(" ");

            // we are recording the work being used by the user and
            // system(work) and the total info
            // of cpu stuff (total)
            // https://mcmap.net/q/270884/-how-to-get-total-cpu-usage-in-linux-using-c/3017438#3017438

            long work1 = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
                    + Long.parseLong(toks[3]);
            long total1 = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
                    + Long.parseLong(toks[3]) + Long.parseLong(toks[4])
                    + Long.parseLong(toks[5]) + Long.parseLong(toks[6])
                    + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);

            try {
                // short sleep time = less accurate. But android devices
                // typically don't have more than
                // 4 cores, and I'n my app, I run this all in a second. So,
                // I need it a bit shorter
                Thread.sleep(300);
            } catch (Exception e) {
            }

            reader.seek(0);
            // skip to the line we need
            for (int ii = 0; ii < i + 1; ++ii) {
                reader.readLine();
            }
            load = reader.readLine();

            // cores will eventually go offline, and if it does, then it is
            // at 0% because it is not being
            // used. so we need to do check if the line we got contains cpu,
            // if not, then this core = 0%
            if (load.contains("cpu")) {
                reader.close();
                toks = load.split(" ");

                long work2 = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
                        + Long.parseLong(toks[3]);
                long total2 = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
                        + Long.parseLong(toks[3]) + Long.parseLong(toks[4])
                        + Long.parseLong(toks[5]) + Long.parseLong(toks[6])
                        + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);

                // here we find the change in user work and total info, and
                // divide by one another to get our total
                // seems to be accurate need to test on quad core
                // https://mcmap.net/q/270884/-how-to-get-total-cpu-usage-in-linux-using-c/3017438#3017438

                 if ((total2 - total1) == 0)
                     return 0;
                 else 
                     return (float) (work2 - work1) / ((total2 - total1));

            } else {
                reader.close();
                return 0;
            }

        } else {
            reader.close();
            return 0;
        }

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

    return 0;
}

Hope it helps!

Developing answered 22/10, 2014 at 15:32 Comment(2)
cool yo! I'll probably add this check to my own stuff. Though, I've been using my code for almost a year now and it's actually never divided by zero...But I guess it's better to be safe than sorry, thanks dude!Nadaba
Also, I know this is super old, but I ended up using this in my Android System monitor widget, that is open sourced on github: github.com/torch2424/Stats-Monitor-Widget/blob/master/app/src/…Nadaba
A
1

The answers of @Torch2424 and @Andre are ok but for my uses they lack several things:

  • I don't want to put a sleep in between the two poll. I prefer to get CPU usage since last function call and decide elsewhere when to call cpuusage function.
  • I think there is a bug in how it counts the cores usage: when a core goes offline it doesn't always assign the core result to the right location of the prev core array.
  • I need a function that returns the global CPU usage.

Here is the code that hopefully fix correctly this: available as a class or as a simple app.

Ardrey answered 29/4, 2018 at 15:58 Comment(3)
I've used your code, and it works out of the box, thanks a lot !!Dump
for info: I updated my code (on github.com/souch/AndroidCPU) so that it can handle android oreo+Ardrey
this is a link only answer you'd need to add significants part of your code in the question itself not in linksMathew
D
0

I have been searching about how to get CPU usage from android for days and nights and I run into that problem some times.

Well, if I am not wrong I think that when you don't get a CPU core means that the core that is not been displayed is offline (android do so to prevent huge battery drain).

If you want to find out how many core the android has find another way, there are tooooons out there, and then do whatever you like.

Dickens answered 9/6, 2014 at 22:35 Comment(1)
Can point to the Android documentation stating that it stops cores for better battery life?Certify
P
0

I hope its works for you...

public static float cpuTemperature() {
    Process process;
    try {
        process = Runtime.getRuntime().exec("cat sys/class/thermal/thermal_zone0/temp");
        process.waitFor();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = reader.readLine();
        if (line != null) {
            float temp = Float.parseFloat(line);
            return temp / 1000.0f;
        } else {
            return 45.0f;
        }
    } catch (Exception e) {
        e.printStackTrace();
        return 0.0f;
    }
}
Pomp answered 8/11, 2021 at 11:53 Comment(1)
Thanks for trying to contribute, but your answer is not on topic. The question is about reading cpu load, and your answer is about cpu temperature.Certify

© 2022 - 2024 — McMap. All rights reserved.