Emmagee学习之获取内存及CPU占用等数据

kybv7973 7年前
   <p>Emmagee 是网易杭州研究院QA团队开发的一个简单易上手的Android性能监测小工具,主要用于监控单个App的CPU,内存,流量,启动耗时,电量,电流等性能状态的变化,且用户可自定义配置监控的频率以及性能的实时显示,并最终生成一份性能统计文件。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/2032017491f08ef2642dae68407c575e.png"></p>    <p style="text-align:center">这里写图片描述</p>    <p>测试QQ的效果如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/8387d2ce3e31d4438f6bf97ee59e2735.jpg"></p>    <p style="text-align:center">这里写图片描述</p>    <pre>  <code class="language-java">/**       *  通过pid获取应用占用的内存       * @return       */      public int getPidMemorySize(int pid, Context context) {          ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);          int[] myMempid = new int[] { pid };          Debug.MemoryInfo[] memoryInfo = am.getProcessMemoryInfo(myMempid);          memoryInfo[0].getTotalSharedDirty();          int memSize = memoryInfo[0].getTotalPss();          return memSize;      }</code></pre>    <pre>  <code class="language-java">/**       * 获取设备可用内存       */      public long getFreeMemorySize(Context context) {          ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();          ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);          am.getMemoryInfo(outInfo);          long avaliMem = outInfo.availMem;          return avaliMem / 1024;      }</code></pre>    <pre>  <code class="language-java">/**       * 获取设备总内存       */      public long getTotalMemory() {          String memInfoPath = "/proc/meminfo";          String readTemp = "";          String memTotal = "";          long memory = 0;          try {              FileReader fr = new FileReader(memInfoPath);              BufferedReader localBufferedReader = new BufferedReader(fr, 8192);              while ((readTemp = localBufferedReader.readLine()) != null) {                  if (readTemp.contains("MemTotal")) {                      String[] total = readTemp.split(":");                      memTotal = total[1].trim();                  }              }              localBufferedReader.close();              String[] memKb = memTotal.split(" ");              memTotal = memKb[0].trim();              Log.d(LOG_TAG, "memTotal: " + memTotal);              memory = Long.parseLong(memTotal);          } catch (IOException e) {              Log.e(LOG_TAG, "IOException: " + e.getMessage());          }          return memory;      }</code></pre>    <pre>  <code class="language-java">/**       * 获取dalvik与native分别占用的内存,仅root可用       */      public static String[][] parseMeminfo(int pid) {            boolean infoStart = false;          // [][],00:native heap size,01:native heap alloc;10: dalvik heap          // size,11: dalvik heap alloc          String[][] heapData = new String[2][2];            try {              Runtime runtime = Runtime.getRuntime();              process = runtime.exec("su");              DataOutputStream os = new DataOutputStream(process.getOutputStream());              os.writeBytes("dumpsys meminfo " + pid + "\n");              os.writeBytes("exit\n");              os.flush();                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));              String line = "";                while ((line = bufferedReader.readLine()) != null) {                  line = line.trim();                  if (line.contains("Permission Denial")) {                      break;                  } else {                      // 当读取到MEMINFO in pid 这一行时,下一行就是需要获取的数据                      if (line.contains("MEMINFO in pid")) {                          infoStart = true;                      } else if (infoStart) {                          String[] lineItems = line.split("\\s+");                          int length = lineItems.length;                          if (line.startsWith("size")) {                              heapData[0][0] = lineItems[1];                              heapData[1][0] = lineItems[2];                          } else if (line.startsWith("allocated")) {                              heapData[0][1] = lineItems[1];                              heapData[1][1] = lineItems[2];                              break;                          } else if (line.startsWith("Native")) {                              Log.d(LOG_TAG, "Native");                              Log.d(LOG_TAG, "lineItems[4]=" + lineItems[4]);                              Log.d(LOG_TAG, "lineItems[5]=" + lineItems[5]);                              heapData[0][0] = lineItems[length-3];                              heapData[0][1] = lineItems[length-2];                          } else if (line.startsWith("Dalvik")) {                              Log.d(LOG_TAG, "Dalvik");                              Log.d(LOG_TAG, "lineItems[4]=" + lineItems[4]);                              Log.d(LOG_TAG, "lineItems[5]=" + lineItems[5]);                              heapData[1][0] = lineItems[length-3];                              heapData[1][1] = lineItems[length-2];                              break;                          }                      }                  }              }          } catch (IOException e) {              e.printStackTrace();          }          return heapData;      }</code></pre>    <pre>  <code class="language-java">/**       * 获取cpu个数,即处理器核心数       * @return       */      public int getCpuNum() {          try {              // Get directory containing CPU info              File dir = new File("/sys/devices/system/cpu/");              // Filter to only list the devices we care about              File[] files = dir.listFiles(new CpuFilter());              return files.length;          } catch (Exception e) {              e.printStackTrace();              return 1;          }      }</code></pre>    <pre>  <code class="language-java">/**       * 获取cpu列表       */      public ArrayList<String> getCpuList() {          ArrayList<String> cpuList = new ArrayList<String>();          try {              // Get directory containing CPU info              File dir = new File("/sys/devices/system/cpu/");              // Filter to only list the devices we care about              File[] files = dir.listFiles(new CpuFilter());              for (int i = 0; i < files.length; i++) {                  cpuList.add(files[i].getName());              }              return cpuList;          } catch (Exception e) {              e.printStackTrace();              cpuList.add("cpu0");              return cpuList;          }      }</code></pre>    <pre>  <code class="language-java">public String getCpuName() {          try {              RandomAccessFile cpuStat = new RandomAccessFile("/proc/cpuinfo", "r");              // check cpu type              String line;              while (null != (line = cpuStat.readLine())) {                  String[] values = line.split(":");                  if (values[0].contains("model name") || values[0].contains("Processor")) {                      cpuStat.close();                      Log.d(LOG_TAG, "CPU name="+values[1]);                      return values[1];                  }              }          } catch (IOException e) {              Log.e(LOG_TAG, "IOException: " + e.getMessage());          }          return "";      }</code></pre>    <pre>  <code class="language-java">/**       * 获取网络流量,上传和下载的总和       */      public long getTrafficInfo() {          Log.i(LOG_TAG, "get traffic information");            long rcvTraffic = -1;          long sndTraffic = -1;            // Use getUidRxBytes and getUidTxBytes to get network traffic,these API          // return both tcp and udp usage          rcvTraffic = TrafficStats.getUidRxBytes(Integer.parseInt(uid));          sndTraffic = TrafficStats.getUidTxBytes(Integer.parseInt(uid));            if (rcvTraffic == -1 || sndTraffic == -1) {              return -1;          } else              return rcvTraffic + sndTraffic;      }</code></pre>    <p>cpu使用率的计算稍微有些不同:</p>    <pre>  <code class="language-java">// 先获取当前pid的占用情况          String processPid = Integer.toString(pid);          String cpuStatPath = "/proc/" + processPid + "/stat";          try {              // monitor cpu stat of certain process              RandomAccessFile processCpuInfo = new RandomAccessFile(cpuStatPath, "r");              String line = "";              StringBuffer stringBuffer = new StringBuffer();              stringBuffer.setLength(0);              while ((line = processCpuInfo.readLine()) != null) {                  stringBuffer.append(line + "\n");              }              String[] tok = stringBuffer.toString().split(" ");              processCpu = Long.parseLong(tok[13]) + Long.parseLong(tok[14]);              processCpuInfo.close();          } catch (FileNotFoundException e) {              Log.w(LOG_TAG, "FileNotFoundException: " + e.getMessage());          } catch (IOException e) {              e.printStackTrace();          }</code></pre>    <pre>  <code class="language-java">// 再获取总的cpu使用情况          try {              // monitor total and idle cpu stat of certain process              RandomAccessFile cpuInfo = new RandomAccessFile(CPU_STAT, "r");              String line = "";              while ((null != (line = cpuInfo.readLine())) && line.startsWith("cpu")) {                  String[] toks = line.split("\\s+");                  idleCpu.add(Long.parseLong(toks[4]));                  totalCpu.add(Long.parseLong(toks[1]) + Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[4])                          + Long.parseLong(toks[6]) + Long.parseLong(toks[5]) + Long.parseLong(toks[7]));              }              cpuInfo.close();          } catch (FileNotFoundException e) {              e.printStackTrace();          } catch (IOException e) {              e.printStackTrace();          }</code></pre>    <p>当前进行所占CPU的算法是:100*(processCpuTimeS-processCpuTimeF) / (totalCpuTimeS-totalCpuTimeF)</p>    <p>CPU总数用率的算法是:100*((totalCpuTimeS-totalCpuTimeF) - (idelS-idelF)) / (totalCpuTimeS - totalCpuTimeF)</p>    <p> </p>    <pre>  <code class="language-java">if (null != totalCpu2 && totalCpu2.size() > 0) {                      processCpuRatio = fomart.format(100 * ((double) (processCpu - processCpu2) / ((double) (totalCpu.get(0) - totalCpu2.get(0)))));                        for (int i = 0; i < (totalCpu.size() > totalCpu2.size() ? totalCpu2.size() : totalCpu.size()); i++) {                          String cpuRatio = "0.00";                          if (totalCpu.get(i) - totalCpu2.get(i) > 0) {                              cpuRatio = fomart                                      .format(100 * ((double) ((totalCpu.get(i) - idleCpu.get(i)) - (totalCpu2.get(i) - idleCpu2.get(i))) / (double) (totalCpu                                              .get(i) - totalCpu2.get(i))));                          }                          totalCpuRatio.add(cpuRatio);                          totalCpuBuffer.append(cpuRatio + Constants.COMMA);                      }                  } else { // 保存前一次的cpu使用情况                      processCpuRatio = "0";                      totalCpuRatio.add("0");                      totalCpuBuffer.append("0,");                      totalCpu2 = (ArrayList<Long>) totalCpu.clone();                      processCpu2 = processCpu;                      idleCpu2 = (ArrayList<Long>) idleCpu.clone();                  }</code></pre>    <p> </p>    <p>来自:http://www.jianshu.com/p/220b2873cb4e</p>    <p> </p>