根据最近的调研,Android整机的性能主要有如下方面:
1、CPU
2、内存
3、耗电量
4、网络
本文着重介绍CPU相关数据的获取,在多核情况下,对每个CPU运行情况进行监控,获取相关的属性。
A. 当前主频,通过 cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq 获取,cpu0代表第一个CPU
B. 最大主频,通过 cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq 获取,cpu0代表第一个CPU
C. 最小主频,通过 cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq 获取,cpu0代表第一个CPU
D.使用率,通过 cat /proc/stat 获取,文件内容如下:第一行代表整体CPU的使用情况,cpu0为第一个cpu的使用情况,不同的列数代表cpu的耗时情况,如第4列代表的就是空闲时间idle的值。
shell@V4:/ $ cat proc/stat
cat proc/stat
cpu 3866978 127487 3035722 26246226 432119 27 52118 0 0
cpu0 3004154 33263 2209598 18130481 92464 16 51202 0 0 0
也就是说使用率我们无法直接获取,需要通过计算,具体的计算方式如下:
usage=(total-idel)/total
说明:使用率指得是cpu在某段时间内被使用的比率,因此事关两个时刻(t1、t2)的值。
分别需要在t1时刻和t2时刻获取total和idel
t1时刻获取: total_t1=所有值相加(同一行) idle_t1=第4个数值
t2时刻获取: total_t2=所有值相加(同一行) idle_t2=第4个数值
上述公式中的
total = total_t2 - total_t1
idle = idle_t2 - idle_t1
这是在国外的资料中说的,可是事实上运行的时候,这样的计算方式可能会出现负数,这边还有点疑问,如果哪位大神知道,麻烦指教。
此外,还有一些CPU的名称,核数信息等,此处不做详解。
下面给出一个类CPUManager,为了避免编码问题,直接用英文写的注释,如有语法错误。。。看懂就行
package com.performancemonitor.tools;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import android.util.Log;
public class CPUManager {
// CPU index
public int CPU_index = 0;
// sampling time in calculate usage
public int sample_fre = DataManager.sample_fre;
public CPUManager(int index) {
this.CPU_index = index;
}
/**
* Wether the CPU is online
* @return true if it is online
*/
public boolean isOnline() {
BufferedReader reader;
String result = "";
ProcessBuilder cmd;
InputStream in = null;
try {
String[] args = { "/system/bin/cat",
"/sys/devices/system/cpu/cpu" + CPU_index + "/online" };
cmd = new ProcessBuilder(args);
Process process = cmd.start();
in = process.getInputStream();
reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String temp = "";
while ((result = reader.readLine()) != null) {
temp = temp + result;
}
if (temp.equals("1")) {
return true;
}
in.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return false;
}
/**
* get the cpu's max frequency, return cpu0 max frequency by defalut
* "/system/bin/cat"
* "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"
*/
public int getMaxCpuFreq() {
String result = "";
String[] args = {
"/system/bin/cat",
"/sys/devices/system/cpu/cpu" + CPU_index
+ "/cpufreq/cpuinfo_max_freq" };
if (!isOnline()) {
args[1] = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
}
ProcessBuilder cmd;
try {
cmd = new ProcessBuilder(args);
Process process = cmd.start();
InputStream in = process.getInputStream();
byte[] re = new byte[24];
while (in.read(re) != -1) {
result = result + new String(re);
}
in.close();
} catch (IOException ex) {
ex.printStackTrace();
result = "0";
}
int max_fre = Integer.parseInt(result.trim()) / 1024;
return max_fre;
}
/**
* get the cpu's min frequency,return cpu0 min frequency by defalut
*/
public int getMinCpuFreq() {
String result = "";
ProcessBuilder cmd;
String[] args = {
"/system/bin/cat",
"/sys/devices/system/cpu/cpu" + CPU_index
+ "/cpufreq/cpuinfo_min_freq" };
if (!isOnline()) {
args[1] = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq";
}
try {
cmd = new ProcessBuilder(args);
Process process = cmd.start();
InputStream in = process.getInputStream();
byte[] re = new byte[24];
while (in.read(re) != -1) {
result = result + new String(re);
}
in.close();
} catch (IOException ex) {
ex.printStackTrace();
result = "-1";
}
int min_fre = Integer.parseInt(result.trim()) / 1024;
return min_fre;
}
/**
* get the cpu's current frequency
*/
public int getCurCpuFreq() {
String result = "";
int cur_fre = 0;
if (!isOnline()) {
result = "0";
return 0;
}
try {
FileReader fr = new FileReader("/sys/devices/system/cpu/cpu"
+ CPU_index + "/cpufreq/scaling_cur_freq");
BufferedReader br = new BufferedReader(fr);
String text = br.readLine();
result = text.trim();
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
return 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
cur_fre = Integer.parseInt(result) / 1024;
return cur_fre;
}
/**
* get the cpu name
*/
public static String getCpuName() {
try {
FileReader fr = new FileReader("/proc/cpuinfo");
BufferedReader br = new BufferedReader(fr);
String text = br.readLine();
String[] array = text.split(":\\s+", 2);
for (int i = 0; i < array.length; i++) {
}
return array[1];
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* get the device's cpu num
*/
public static int getNumCores() {
class CpuFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
if (Pattern.matches("cpu[0-9]", pathname.getName())) {
return true;
}
return false;
}
}
try {
File dir = new File("/sys/devices/system/cpu/");
File[] files = dir.listFiles(new CpuFilter());
return files.length;
} catch (Exception e) {
Log.e("cxq", "CPU Count: Failed.");
e.printStackTrace();
return 1;
}
}
/**
* get the cpu usage using specified samplling time
*/
public double getUsage() {
double usage = 0;
long total_start, total_end;
long idel_start, idel_end;
try {
Map start_data = getCPUData();
idel_start = start_data.get("idle");
total_start = start_data.get("total_time");
Thread.sleep(sample_fre);
Map end_data = getCPUData();
idel_end = end_data.get("idle");
total_end = end_data.get("total_time");
double idel = idel_end - idel_start;
double total = total_end - total_start;
if (total == 0) {
return 0;
}
usage = (total - idel) / total;
usage = Math.abs(usage * 100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DecimalFormat df = new java.text.DecimalFormat("#.00");
usage = Double.parseDouble(df.format(usage));
return usage;
}
/**
* take a data snapshot avoid reading the old data, especially using for usage calculation
* @return Map it contains two values,("total_time",total_time) and ("idle",idle);
*/
public Map getCPUData() {
Map data = new HashMap();
ArrayList list = new ArrayList();
ArrayList list_defalut = new ArrayList();
for (int i = 0; i < 10; i++) {
list_defalut.add(0L);
}
String cpuCompare = "cpu" + CPU_index;
if (CPU_index == -1) {
cpuCompare = "cpu";
}
String load = "";
String[] temp = null;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/stat")), 1000);
while ((load = reader.readLine()) != null) {
if (load.contains(cpuCompare)) {
break;
} else {
load = "";
}
}
reader.close();
if (load == null || load.equals("")) {
data.put("total_time", 0L);
data.put("idle", 0L);
return data;
}
temp = load.split(" ");
for (int i = 1; i < temp.length; i++) {
if (!temp[i].trim().equals("")) {
list.add(Long.parseLong(temp[i]));
}
}
} catch (IOException ex) {
Log.e("CPU", "IOException" + ex.toString());
data.put("total_time", 0L);
data.put("idle", 0L);
return data;
}
long total_time = 0;
for (int i = 0; i < list.size(); i++) {
total_time += list.get(i);
}
data.put("total_time", total_time);
data.put("idle", list.get(3));
return data;
}
}
如果要获取整个CPU的情况,则CPU_index=-1,该情况下无主频,如果要获取cpu0的情况,则在构造函数里面传0,以此类推
CPUManager total_cpu=new CPUManager(i);
double usage=total_cpu.getUsage()
其他性能方面的数据获取,还有待补充。。。。