Skip to content

Commit a0e7c58

Browse files
committed
do not reopen stat file for each core
1 parent 8f42cbd commit a0e7c58

File tree

3 files changed

+107
-86
lines changed

3 files changed

+107
-86
lines changed

.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/src/main/java/souch/androidcpu/CpuInfo.java

+99-84
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@
88

99
public class CpuInfo {
1010

11-
/* @return total cpu usage since last call (from 0 to 100)
12-
* note:
13-
* - first call always returns 0 as previous value is not initialized
11+
/*
12+
* @return total cpu usage (from 0 to 100) since last call of getCpuUsage or getCoresUsage
13+
*/
14+
public static int getCpuUsage() {
15+
return getCpuUsage(getCoresUsage());
16+
}
17+
18+
/* @return total cpu usage (from 0 to 100) since last call of getCpuUsage or getCoresUsage
19+
* first call always returns 0 as previous value is not known
1420
* @param coresUsage must come from getCoresUsage().
1521
*/
1622
public static int getCpuUsage(float[] coresUsage) {
@@ -27,61 +33,75 @@ public static int getCpuUsage(float[] coresUsage) {
2733
return (int) (cpuUsage * 100 / (coresUsage.length - 1));
2834
}
2935

30-
public static int getCpuUsage() {
31-
return getCpuUsage(getCoresUsage());
32-
}
33-
34-
private static class CpuStat {
35-
float active;
36-
float total;
37-
38-
CpuStat(float active, float total) {
39-
this.active = active;
40-
this.total = total;
41-
}
42-
}
43-
44-
private static ArrayList<CpuStat> mPrevCpuStats;
4536
/*
46-
* @return array of cores usage since last call.
37+
* @return array of cores usage since last call
38+
* (first call always returns -1 as the func has never been called).
4739
* array size = nbcore +1 as the first element is for global cpu usage
48-
* array element : < 0 -> cpu unavailable ; 0 -> cpu min ; 1 -> cpu max
40+
* First element is global CPU usage from stat file (which does not consider offline core !
41+
* Use getCpuUsage do get proper global CPU usage)
42+
* array element: < 0 => cpu unavailable ; 0 => cpu min ; 1 => cpu max
4943
*/
5044
public static synchronized float[] getCoresUsage() {
5145
int numCores = getNumCores() + 1; // +1 for global cpu stat
5246

5347
// ensure mPrevCores list is big enough
54-
if (mPrevCpuStats == null)
55-
mPrevCpuStats = new ArrayList<>();
56-
while(mPrevCpuStats.size() < numCores)
57-
mPrevCpuStats.add(null);//new CpuStat(-1, -1));
48+
if (mPrevCoreStats == null)
49+
mPrevCoreStats = new ArrayList<>();
50+
while(mPrevCoreStats.size() < numCores)
51+
mPrevCoreStats.add(null);//new CpuStat(-1, -1));
5852

5953
// init cpuStats
60-
ArrayList<CpuStat> cpuStats = new ArrayList<>();
61-
while(cpuStats.size() < numCores)
62-
cpuStats.add(null);
54+
ArrayList<CoreStat> coreStats = new ArrayList<>();
55+
while(coreStats.size() < numCores)
56+
coreStats.add(null);
6357

6458
float[] coresUsage = new float[numCores];
6559

66-
// get current cpu stat
67-
for (byte i = 0; i < numCores; i++) {
68-
// todo: do not reopen stat file for each core
69-
CpuStat curCpuStat = readCpuStat(i);
70-
coresUsage[i] = -1;
71-
if (curCpuStat != null) {
72-
CpuStat prevCpuStat = mPrevCpuStats.get(i);
73-
if (prevCpuStat != null) {
74-
float diffActive = curCpuStat.active - prevCpuStat.active;
75-
float diffTotal = curCpuStat.total - prevCpuStat.total;
76-
// check for strange values
77-
if (diffActive > 0 && diffTotal > 0)
78-
// compute usage
79-
coresUsage[i] = diffActive / diffTotal;
60+
try {
61+
/* cat /proc/stat # example of possible output
62+
* cpu 193159 118453 118575 7567474 4615 6 2312 0 0 0
63+
* cpu0 92389 116352 96662 2125638 2292 5 2021 0 0 0
64+
* cpu3 47648 1264 11220 2378965 1286 0 9 0 0 0
65+
* ...
66+
*/
67+
RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
68+
69+
try {
70+
CoreStat curCoreStat = null;
71+
String line = reader.readLine();
72+
73+
for (byte i = 0; i < numCores; i++) {
74+
coresUsage[i] = -1;
75+
// if cpu lines
76+
if (line.contains("cpu")) {
77+
// try get core stat number i
78+
curCoreStat = readCoreStat(i, line);
79+
if (curCoreStat != null) {
80+
CoreStat prevCoreStat = mPrevCoreStats.get(i);
81+
if (prevCoreStat != null) {
82+
float diffActive = curCoreStat.active - prevCoreStat.active;
83+
float diffTotal = curCoreStat.total - prevCoreStat.total;
84+
// check for strange values
85+
if (diffActive > 0 && diffTotal > 0)
86+
// compute usage
87+
coresUsage[i] = diffActive / diffTotal;
88+
}
89+
90+
// cur becomes prev (only if cpu online)
91+
mPrevCoreStats.set(i, curCoreStat);
92+
93+
// load another line only if corresponding core has been found
94+
// otherwise try next core number with same line
95+
line = reader.readLine();
96+
}
97+
}
8098
}
8199

82-
// cur becomes prev (only if cpu online)
83-
mPrevCpuStats.set(i, curCpuStat);
100+
} finally {
101+
reader.close();
84102
}
103+
} catch (Exception ex) {
104+
ex.printStackTrace();
85105
}
86106

87107
return coresUsage;
@@ -90,57 +110,52 @@ public static synchronized float[] getCoresUsage() {
90110
/* return CpuStat read, or null if it could not be read (e.g. cpu offline)
91111
* @param coreNum coreNum=0 return global cpu state, coreNum=1 return first core
92112
*
93-
* cat /proc/stat # example of possible output
94-
* cpu 193159 118453 118575 7567474 4615 6 2312 0 0 0
95-
* cpu0 92389 116352 96662 2125638 2292 5 2021 0 0 0
96-
* cpu3 47648 1264 11220 2378965 1286 0 9 0 0 0
97-
* ...
98-
*
99113
* adapted from https://stackoverflow.com/questions/22405403/android-cpu-cores-reported-in-proc-stat
100114
*/
101-
private static CpuStat readCpuStat(int coreNum) {
102-
CpuStat cpuStat = null;
103-
115+
private static CoreStat readCoreStat(int coreNum, String line) {
116+
CoreStat coreStat = null;
104117
try {
105-
RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
106-
107-
try {
108-
String cpuStr;
109-
if (coreNum > 0)
110-
cpuStr = "cpu" + (coreNum - 1) + " ";
111-
else
112-
cpuStr = "cpu ";
113-
114-
// cores will eventually go offline, so we need to do check every lines
115-
// read at most coreNum+1 line
116-
for (int i = 0; i < coreNum + 1; ++i) {
117-
String load = reader.readLine();
118-
if (load.contains(cpuStr)) {
119-
String[] toks = load.split(" +");
120-
121-
// we are recording the work being used by the user and
122-
// system(work) and the total info of cpu stuff (total)
123-
// http://stackoverflow.com/questions/3017162/how-to-get-total-cpu-usage-in-linux-c/3017438#3017438
124-
long active = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
125-
+ Long.parseLong(toks[3]);
126-
long total = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
127-
+ Long.parseLong(toks[3]) + Long.parseLong(toks[4])
128-
+ Long.parseLong(toks[5]) + Long.parseLong(toks[6])
129-
+ Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
130-
131-
cpuStat = new CpuStat(active, total);
132-
}
133-
}
134-
} finally {
135-
reader.close();
118+
String cpuStr;
119+
if (coreNum > 0)
120+
cpuStr = "cpu" + (coreNum - 1) + " ";
121+
else
122+
cpuStr = "cpu ";
123+
124+
if (line.contains(cpuStr)) {
125+
String[] toks = line.split(" +");
126+
127+
// we are recording the work being used by the user and
128+
// system(work) and the total info of cpu stuff (total)
129+
// http://stackoverflow.com/questions/3017162/how-to-get-total-cpu-usage-in-linux-c/3017438#3017438
130+
long active = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
131+
+ Long.parseLong(toks[3]);
132+
long total = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
133+
+ Long.parseLong(toks[3]) + Long.parseLong(toks[4])
134+
+ Long.parseLong(toks[5]) + Long.parseLong(toks[6])
135+
+ Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
136+
137+
coreStat = new CoreStat(active, total);
136138
}
137139
} catch (Exception ex) {
138140
ex.printStackTrace();
139141
}
142+
return coreStat;
143+
}
144+
145+
private static class CoreStat {
146+
float active;
147+
float total;
140148

141-
return cpuStat;
149+
CoreStat(float active, float total) {
150+
this.active = active;
151+
this.total = total;
152+
}
142153
}
143154

155+
// previous stat read
156+
private static ArrayList<CoreStat> mPrevCoreStats;
157+
158+
144159
// from https://stackoverflow.com/questions/7962155/how-can-you-detect-a-dual-core-cpu-on-an-android-device-from-code
145160
/**
146161
* Gets the number of cores available in this device, across all processors.

app/src/main/java/souch/androidcpu/MainActivity.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ public void onClick(View view) {
3434
if (cores[i] < 0)
3535
info += " x";
3636
else
37-
info += " " + (int) (cores[i] * 100);
37+
info += " " + (int) (cores[i] * 100) + "%";
3838
}
39-
info += ", CPU total: " + CpuInfo.getCpuUsage(cores);
39+
info += ", CPU total: " + CpuInfo.getCpuUsage(cores) + "%";
4040

4141
text.setText(info);
4242

0 commit comments

Comments
 (0)