Android整机性能监控:多核CPU相关数据的获取(使用率、主频)

根据最近的调研,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()

其他性能方面的数据获取,还有待补充。。。。

你可能感兴趣的:(android)