| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 | #include "platform/android/jni/ProcessCpuTracker.h"#ifdef ANDROID#include <jni.h>#include <android/log.h>#endif#include <stdlib.h>#include <vector>#include <time.h>#include <fcntl.h>#include <sstream>#ifdef ANDROID#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "ProcessCpuTracker", __VA_ARGS__)#else#define LOGD printf#endiftypedef struct _CpuInfo{    long userTime; // Unit: jiffies    long niceTime;    long systemTime;    long idleTime;    long ioWaitTime;    long irqTime;    long softIrqTime;}CpuInfo;// Return 0 means the end of bufferstatic bool readLine(char* p, const char* end, char** next){    if (p == NULL)    {        *next = NULL;        return false;    }    while (*p != '\n' && p < end)        ++p;    if (*p == '\n')    {// line break        *p = '\0'; // Set to \0 to make a sub-sequence string        *next = ++p;        return true;    }    else    {// end of buffer        *next = NULL;        return true;    }}static std::vector<CpuInfo> readProcStat(){    std::vector<CpuInfo> cpuInfos;    cpuInfos.reserve(13);    char buffer[1024] = {0};#ifdef ANDROID    int fd = open("/proc/stat", O_RDONLY);    if (fd < 0)    {        return cpuInfos;    }    const int len = read(fd, buffer, sizeof(buffer)-1);    close(fd);    if (len < 0) {        LOGD("Unable to open process fd=%d", fd);        return cpuInfos;    }    buffer[len] = 0;#else    FILE* fp = fopen("fonts/stat-huawei.txt", "rb");    if (fp == NULL)        return cpuInfos;    fread(buffer, sizeof(buffer)-1, 1, fp);    fclose(fp);    size_t len = strlen(buffer);#endif    char* p = buffer;    const char* end = p + len;    char* next = NULL;    int cpuIndex;    const int COLUMN = sizeof(CpuInfo) / sizeof(long);    size_t i = 0;    while (readLine(p, end, &next))    {        // break if the line with no cpu prefix        if (p[0] != 'c' || p[1] != 'p' || p[2] != 'u')            break;//        LOGD("%s\n", p);        // Removes 'cpu%d' prefix        p = p + 3;        if (*p == ' ')        { // The first line means the average cpu usage            cpuIndex = 0;        }        else        {            cpuIndex = strtol(p, &p, 10) + 1;        }//        LOGD("cpu index: %d\n", cpuIndex);        cpuInfos.resize(cpuIndex + 1);        for (i = 0; i < COLUMN; ++i)        {            long value = strtol(p, &p, 10);//            LOGD("%ld ", value);            CpuInfo& info = cpuInfos[cpuIndex];            long* e = (long*)&info + i;            *e = value;        }//        LOGD("%s", "\n");        p = next;    }    return cpuInfos;}void ProcessCpuTracker::update(){    static const int JIFFYMILLIS = 10;    std::vector<CpuInfo> cpuInfos = readProcStat();    if (!cpuInfos.empty())    {        if (_cpuTimeInfos.size() < cpuInfos.size())        {            _cpuTimeInfos.resize(cpuInfos.size());        }//        LOGD("cpuInfo size: %d", (int)cpuInfos.size());        for (size_t i = 0, len = cpuInfos.size(); i < len; ++i)        {            CpuTimeInfo& cpuTimeInfo = _cpuTimeInfos[i];            const CpuInfo& cpuInfo = cpuInfos[i];            // Total user time is user + nice time.            const long usertime = (cpuInfo.userTime + cpuInfo.niceTime) * JIFFYMILLIS;            // Total system time is simply system time.            const long systemtime = cpuInfo.systemTime * JIFFYMILLIS;            // Total idle time is simply idle time.            const long idletime = cpuInfo.idleTime * JIFFYMILLIS;            // Total irq time is iowait + irq + softirq time.            const long iowaittime = cpuInfo.ioWaitTime * JIFFYMILLIS;            const long irqtime = cpuInfo.irqTime * JIFFYMILLIS;            const long softirqtime = cpuInfo.softIrqTime * JIFFYMILLIS;            // This code is trying to avoid issues with idle time going backwards,            // but currently it gets into situations where it triggers most of the time. :(            if (false || (usertime >= cpuTimeInfo.mBaseUserTime && systemtime >= cpuTimeInfo.mBaseSystemTime                         && iowaittime >= cpuTimeInfo.mBaseIoWaitTime && irqtime >= cpuTimeInfo.mBaseIrqTime                         && softirqtime >= cpuTimeInfo.mBaseSoftIrqTime && idletime >= cpuTimeInfo.mBaseIdleTime)) {                cpuTimeInfo.mRelUserTime = usertime - cpuTimeInfo.mBaseUserTime;                cpuTimeInfo.mRelSystemTime = systemtime - cpuTimeInfo.mBaseSystemTime;                cpuTimeInfo.mRelIoWaitTime = iowaittime - cpuTimeInfo.mBaseIoWaitTime;                cpuTimeInfo.mRelIrqTime = irqtime - cpuTimeInfo.mBaseIrqTime;                cpuTimeInfo.mRelSoftIrqTime = softirqtime - cpuTimeInfo.mBaseSoftIrqTime;                cpuTimeInfo.mRelIdleTime = idletime - cpuTimeInfo.mBaseIdleTime;//                if (true) {//                    LOGD("CPU%d, Total U: %ld, N:%ld S:%ld I:%ld W:%ld Q:%ld O:%ld\n",//                         (int)i,//                         cpuInfo.userTime,//                         cpuInfo.niceTime,//                         cpuInfo.systemTime,//                         cpuInfo.idleTime,//                         cpuInfo.ioWaitTime,//                         cpuInfo.irqTime,//                         cpuInfo.softIrqTime//                         );//                    LOGD("CPU%d, Rel U:%ld, S:%ld, I:%ld, Q:%ld\n",//                        (int)i,//                        cpuTimeInfo.mRelUserTime,//                        cpuTimeInfo.mRelSystemTime,//                        cpuTimeInfo.mRelIdleTime,//                        cpuTimeInfo.mRelIrqTime//                        );//                    if (cpuTimeInfo.mRelUserTime < 0//                        || cpuTimeInfo.mRelSystemTime < 0//                        || cpuTimeInfo.mRelIdleTime < 0//                        || cpuTimeInfo.mRelIrqTime < 0)//                    {//                        LOGD("CPU%d,base U:%ld, S:%ld, I:%ld, Q:%ld\n",//                        (int)i,//                        cpuTimeInfo.mBaseUserTime,//                        cpuTimeInfo.mBaseSystemTime,//                        cpuTimeInfo.mBaseIdleTime,//                        cpuTimeInfo.mBaseIrqTime//                        );//                    }//                }                cpuTimeInfo.mBaseUserTime = usertime;                cpuTimeInfo.mBaseSystemTime = systemtime;                cpuTimeInfo.mBaseIoWaitTime = iowaittime;                cpuTimeInfo.mBaseIrqTime = irqtime;                cpuTimeInfo.mBaseSoftIrqTime = softirqtime;                cpuTimeInfo.mBaseIdleTime = idletime;            } else {//                if (usertime < cpuTimeInfo.mBaseUserTime)//                {//                    LOGD("ERROR: usertime: %ld, base: %ld", usertime, cpuTimeInfo.mBaseUserTime);//                }////                if (systemtime < cpuTimeInfo.mBaseSystemTime)//                {//                    LOGD("ERROR: systemtime: %ld, base: %ld", systemtime, cpuTimeInfo.mBaseSystemTime);//                }////                if (iowaittime < cpuTimeInfo.mBaseIoWaitTime)//                {//                    LOGD("ERROR: iowaittime: %ld, base: %ld", iowaittime, cpuTimeInfo.mBaseIoWaitTime);//                }////                if (irqtime < cpuTimeInfo.mBaseIrqTime)//                {//                    LOGD("ERROR: irqtime: %ld, base: %ld", irqtime, cpuTimeInfo.mBaseIrqTime);//                }////                if (softirqtime < cpuTimeInfo.mBaseSoftIrqTime)//                {//                    LOGD("ERROR: softirqtime: %ld, base: %ld", softirqtime, cpuTimeInfo.mBaseSoftIrqTime);//                }////                if (idletime < cpuTimeInfo.mBaseIdleTime)//                {//                    LOGD("ERROR: idletime: %ld, base: %ld", idletime, cpuTimeInfo.mBaseIdleTime);//                }                if (usertime > 0 || idletime > 0)                {                    cpuTimeInfo.mBaseUserTime = usertime;                    cpuTimeInfo.mBaseSystemTime = systemtime;                    cpuTimeInfo.mBaseIoWaitTime = iowaittime;                    cpuTimeInfo.mBaseIrqTime = irqtime;                    cpuTimeInfo.mBaseSoftIrqTime = softirqtime;                    cpuTimeInfo.mBaseIdleTime = idletime;                }                cpuTimeInfo.mRelUserTime = 0;                cpuTimeInfo.mRelSystemTime = 0;                cpuTimeInfo.mRelIoWaitTime = 0;                cpuTimeInfo.mRelIrqTime = 0;                cpuTimeInfo.mRelSoftIrqTime = 0;                cpuTimeInfo.mRelIdleTime = 0;                LOGD("CPU: %d, /proc/stats has gone backwards; skipping CPU update\n", (int)i);            }        }    }}static long printRatio(std::stringstream& ss, long numerator, long denominator) {    long hundreds = 0;    if (denominator > 0)    {        long thousands = (numerator*1000)/denominator;        hundreds = thousands/10;        ss << hundreds;        if (hundreds < 10) {            long remainder = thousands - (hundreds*10);            if (remainder != 0) {                ss << '.';                ss << remainder;            }        }    }    else    {        ss << '0';    }    ss << " ";    return hundreds;}static long printProcessCPU(std::stringstream& ss, long totalTime, long user){       return printRatio(ss, user, totalTime);}void ProcessCpuTracker::printCurrentState(){    std::stringstream ss;    long totalCpuUsage = 0;    for (size_t i = 0, len = _cpuTimeInfos.size(); i < len; ++i)    {        CpuTimeInfo& cpuTimeInfo = _cpuTimeInfos[i];        const long totalTime = cpuTimeInfo.mRelUserTime + cpuTimeInfo.mRelSystemTime + cpuTimeInfo.mRelIoWaitTime        + cpuTimeInfo.mRelIrqTime + cpuTimeInfo.mRelSoftIrqTime + cpuTimeInfo.mRelIdleTime;//        if (totalTime <= 0)//        {//            LOGD("cjh totalTime, i=%d: %ld mRelUserTime: %ld, mRelSystemTime: %ld, mRelIoWaitTime: %ld, mRelIrqTime: %ld, mRelSoftIrqTime: %ld, mRelIdleTime: %ld",//                (int)i,//                totalTime,//                cpuTimeInfo.mRelUserTime,//                cpuTimeInfo.mRelSystemTime,//                cpuTimeInfo.mRelIoWaitTime,//                cpuTimeInfo.mRelIrqTime,//                cpuTimeInfo.mRelSoftIrqTime,//                cpuTimeInfo.mRelIdleTime//            );//        }        const long preCoreUsage = printProcessCPU(ss, totalTime, cpuTimeInfo.mRelUserTime);        if (i > 0)        {            totalCpuUsage += preCoreUsage;        }    }    ss << "T:";    ss << totalCpuUsage;    std::string str = ss.str();    LOGD("CPU: %s", str.c_str());}
 |