Android性能监控小工具
//编译方法如下:
//d:\android-ndk-r8e-windows-x86\android-ndk-r8e为Android NDK根目录
cd d:\android-ndk-r8e-windows-x86\android-ndk-r8e\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\
arm-linux-androideabi-g++.exe -fPIE -pie -fpermissive --sysroot=d:\android-ndk-r8e-windows-x86\android-ndk-r8e\platforms\android-9\arch-arm\ -I d:\android-ndk-r8e-windows-x86\android-ndk-r8e\sources\cxx-stl\stlport\stlport\ -l d:\android-ndk-r8e-windows-x86\android-ndk-r8e\sources\cxx-stl\stlport\libs\armeabi-v7a\libstlport_shared.so e:\itrans\osres_mon_android.cpp -o e:\itrans\osres_mon_android 1>stdout 2>&1
//简略为:g++ -fPIE -pie --sysroot="" -I"\stlport" -l"libstlport_shared.so" osres_mon_android.cpp -o osres_mon_android
//运行方法:
//需依赖libstlport_shared.so共享库,确保该共享库位于链接路径中
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #include
#include // 更新周期,单位微妙,即1秒
#define UPDATE_PERIOD 1000000
#define CALC_FACTOR (1E8/UPDATE_PERIOD)static char *nexttoksep(char **strp, char *sep)
{ char *p = strsep(strp,sep); return (p == 0) ? "" : p;
}
static char *nexttok(char **strp)
{ return nexttoksep(strp, " ");
}
static int ps_line(int pid, unsigned int& ret_vsize, unsigned int& ret_rss)
{ char statline[1024]; char user[32]; struct stat stats; int fd, r; char *ptr, *name, *state; int ppid, tty; unsigned wchan, rss, vss, eip; unsigned utime, stime; int prio, nice, rtprio, sched; struct passwd *pw; sprintf(statline, "/proc/%d", pid); stat(statline, &stats); sprintf(statline, "/proc/%d/stat", pid);fd = open(statline, O_RDONLY); if(fd == 0) return -1; r = read(fd, statline, 1023); close(fd); if(r < 0) return -1; statline[r] = 0; ptr = statline; nexttok(&ptr); // skip pid ptr++; // skip "(" name = ptr; ptr = strrchr(ptr, ')'); // Skip to *last* occurence of ')', *ptr++ = '\0'; // and null-terminate name. ptr++; // skip " " state = nexttok(&ptr); ppid = atoi(nexttok(&ptr)); nexttok(&ptr); // pgrp nexttok(&ptr); // sid tty = atoi(nexttok(&ptr)); nexttok(&ptr); // tpgid nexttok(&ptr); // flags nexttok(&ptr); // minflt nexttok(&ptr); // cminflt nexttok(&ptr); // majflt nexttok(&ptr); // cmajflt
#if 1 utime = atoi(nexttok(&ptr)); stime = atoi(nexttok(&ptr));
#else nexttok(&ptr); // utime nexttok(&ptr); // stime
#endif nexttok(&ptr); // cutime nexttok(&ptr); // cstime prio = atoi(nexttok(&ptr)); nice = atoi(nexttok(&ptr)); nexttok(&ptr); // threads nexttok(&ptr); // itrealvalue nexttok(&ptr); // starttime vss = strtoul(nexttok(&ptr), 0, 10); // vsize rss = strtoul(nexttok(&ptr), 0, 10); // rss nexttok(&ptr); // rlim nexttok(&ptr); // startcode nexttok(&ptr); // endcode nexttok(&ptr); // startstack nexttok(&ptr); // kstkesp eip = strtoul(nexttok(&ptr), 0, 10); // kstkeip nexttok(&ptr); // signal nexttok(&ptr); // blocked nexttok(&ptr); // sigignore nexttok(&ptr); // sigcatch wchan = strtoul(nexttok(&ptr), 0, 10); // wchan nexttok(&ptr); // nswap nexttok(&ptr); // cnswap nexttok(&ptr); // exit signal nexttok(&ptr); // processor rtprio = atoi(nexttok(&ptr)); // rt_priority sched = atoi(nexttok(&ptr)); // scheduling policy tty = atoi(nexttok(&ptr)); //pw = getpwuid(stats.st_uid); //if(pw == 0) { // sprintf(user,"%d",(int)stats.st_uid); //} else { // strcpy(user,pw->pw_name); //} ret_vsize = vss / 1024;ret_rss = rss * 4;return 0;
} unsigned long get_pid_from_cmd(char* cmd_name)
{int pid = -1;DIR *d;struct dirent *de;char cmdline[1024];int fd,r,tmp_pid;// 打开文件夹/procd = opendir("/proc");if(d == 0) return -1;// 遍历/proc下的子文件夹while((de = readdir(d)) != 0){if(isdigit(de->d_name[0])){// 如果文件夹名中含有数字,则可能是某个进程tmp_pid = atoi(de->d_name);sprintf(cmdline, "/proc/%d/cmdline", tmp_pid);// 打开文件/proc/'tmp_pid'/cmdlinefd = open(cmdline, O_RDONLY); if(fd == 0) {r = 0;} else {// 读取文件/proc/'tmp_pid'/cmdliner = read(fd, cmdline, 1023);close(fd);}cmdline[r] = 0;// cmdline长度不为零,且cmd_name为其子串if (0 != strlen(cmdline) && NULL != strstr(cmdline, cmd_name)){pid = tmp_pid;break;}}}closedir(d);
}// 字符串分割
void SplitString(const std::string& s, std::vector& v, const std::string& c)
{std::string::size_type pos1, pos2;pos2 = s.find(c);pos1 = 0;while(std::string::npos != pos2){v.push_back(s.substr(pos1, pos2-pos1));pos1 = pos2 + c.size();pos2 = s.find(c, pos1);}if(pos1 != s.length())v.push_back(s.substr(pos1));
}
static unsigned long getTotalCpuTime()
{// 获取系统总CPU使用时间char fileline[1024]={0};char content[1024]={0};int fd,r;sprintf(fileline, "/proc/stat");// 打开文件/proc/statfd = open(fileline, O_RDONLY); if(fd == 0) {r = 0;} else {// 读取文件/proc/stat到contentr = read(fd, content, 1024 - 1);close(fd);}content[r] = 0;// 对content进行分割std::vector cpuInfos;SplitString(content, cpuInfos, " ");if (cpuInfos.size() >= 9) {unsigned long totalCpuTime = atol(cpuInfos[2].c_str())+ atol(cpuInfos[3].c_str()) + atol(cpuInfos[4].c_str())+ atol(cpuInfos[6].c_str()) + atol(cpuInfos[5].c_str())+ atol(cpuInfos[7].c_str()) + atol(cpuInfos[8].c_str());return totalCpuTime;}else{return 0;}
}
static unsigned long getAppCpuTime(int pid)
{// 获取应用占用的CPU时间char fileline[1024]={0};char content[1024]={0};int fd,r;sprintf(fileline, "/proc/%d/stat", pid);// 打开文件/proc/pid/statfd = open(fileline, O_RDONLY); if(fd == 0) {r = 0;} else {// 读取文件/proc/pid/stat到contentr = read(fd, content, 1024 - 1);close(fd);}content[r] = 0;// 对content进行分割std::vector cpuInfos;SplitString(content, cpuInfos, " ");if (cpuInfos.size() >= 17) {unsigned long appCpuTime = atol(cpuInfos[13].c_str())+ atol(cpuInfos[14].c_str()) + atol(cpuInfos[15].c_str())+ atol(cpuInfos[16].c_str());return appCpuTime;}else{return 0;}
}static float getProcessCpuRate(int pid)
{unsigned long totalCpuTime1 = getTotalCpuTime();unsigned long processCpuTime1 = getAppCpuTime(pid);usleep(UPDATE_PERIOD);unsigned long totalCpuTime2 = getTotalCpuTime();unsigned long processCpuTime2 = getAppCpuTime(pid);if(!totalCpuTime1 || !processCpuTime1 || !totalCpuTime2 || !processCpuTime2)return 0.0f;float cpuRate = 100 * (processCpuTime2 - processCpuTime1)/ (totalCpuTime2 - totalCpuTime1);return cpuRate;
}int main(int argc, char * argv[])
{char cmd[100] = "itranscon";unsigned long pid = -1;unsigned int vsize = 0;unsigned int rss = 0;float cpu_rate = 0.0f;time_t t;if (argc < 2){printf("Usage: osres_mon command\n");printf("Monitoring default process:itranscon!\n");}else{strcpy(cmd,argv[1]);}pid = get_pid_from_cmd(cmd);if (pid == -1){printf("Not find pid named %s\n",cmd);return -1;}FILE* flog = NULL;flog = fopen("osres_mon.log", "w+");if(!flog) {printf("open log file failed!\n");}printf("PID COMMAND VSIZE RSS CPU_RATE TIME\n");if (flog) {fprintf(flog, "PID COMMAND VSIZE RSS CPU_RATE TIME\n");fflush(flog);}//PID 进程ID//COMMAND 进程名称//VSIZE 进程的虚拟内存大小,以KB为单位//RSS 进程实际占用的内存大小,以KB为单位//CPU_RATE 进程的CPU使用率while (true){if (0 != ps_line(pid, vsize, rss)) {printf("ps_line() error!\n");return -1;}cpu_rate = getProcessCpuRate(pid);t = time(NULL);printf("%d\t%s\t%d\t%d\t%.3f%%\t%s\t",pid,cmd,vsize,rss,cpu_rate,asctime(localtime(&t)));if (flog) {fprintf(flog, "%d\t%s\t%d\t%d\t%.3f%%\t%s\t",pid,cmd,vsize,rss,cpu_rate,asctime(localtime(&t)));fflush(flog);}// usleep 单位:微秒(us)(百万分之一秒)usleep(UPDATE_PERIOD);}if (flog)fclose(flog);
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
