您的位置:首页 > 移动开发 > Android开发

Android性能监控小工具

2017-02-23 08:41 316 查看
//编译方法如下:

//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 <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>

#include <vector>
#include <string>

// 更新周期,单位微妙,即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); // ma
4000
jflt
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;

// 打开文件夹/proc
d = 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'/cmdline
fd = open(cmdline, O_RDONLY);
if(fd == 0) {
r = 0;
} else {
// 读取文件/proc/'tmp_pid'/cmdline
r = 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<std::string>& 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/stat
fd = open(fileline, O_RDONLY);
if(fd == 0) {
r = 0;
} else {
// 读取文件/proc/stat到content
r = read(fd, content, 1024 - 1);
close(fd);
}
content[r] = 0;
// 对content进行分割
std::vector<std::string> 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/stat
fd = open(fileline, O_RDONLY);
if(fd == 0) {
r = 0;
} else {
// 读取文件/proc/pid/stat到content
r = read(fd, content, 1024 - 1);
close(fd);
}
content[r] = 0;
// 对content进行分割
std::vector<std::string> 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 <unistd.h> 单位:微秒(us)(百万分之一秒)
usleep(UPDATE_PERIOD);
}
if (flog)
fclose(flog);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: