ProcessCpuTracker.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include "platform/android/jni/ProcessCpuTracker.h"
  2. #ifdef ANDROID
  3. #include <jni.h>
  4. #include <android/log.h>
  5. #include <unistd.h>
  6. #endif
  7. #include <stdlib.h>
  8. #include <vector>
  9. #include <time.h>
  10. #include <fcntl.h>
  11. #include <sstream>
  12. #ifdef ANDROID
  13. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "ProcessCpuTracker", __VA_ARGS__)
  14. #else
  15. #define LOGD printf
  16. #endif
  17. typedef struct _CpuInfo
  18. {
  19. long userTime; // Unit: jiffies
  20. long niceTime;
  21. long systemTime;
  22. long idleTime;
  23. long ioWaitTime;
  24. long irqTime;
  25. long softIrqTime;
  26. }CpuInfo;
  27. // Return 0 means the end of buffer
  28. static bool readLine(char* p, const char* end, char** next)
  29. {
  30. if (p == NULL)
  31. {
  32. *next = NULL;
  33. return false;
  34. }
  35. while (*p != '\n' && p < end)
  36. ++p;
  37. if (*p == '\n')
  38. {// line break
  39. *p = '\0'; // Set to \0 to make a sub-sequence string
  40. *next = ++p;
  41. return true;
  42. }
  43. else
  44. {// end of buffer
  45. *next = NULL;
  46. return true;
  47. }
  48. }
  49. static std::vector<CpuInfo> readProcStat()
  50. {
  51. std::vector<CpuInfo> cpuInfos;
  52. cpuInfos.reserve(13);
  53. char buffer[1024] = {0};
  54. #ifdef ANDROID
  55. int fd = open("/proc/stat", O_RDONLY);
  56. if (fd < 0)
  57. {
  58. return cpuInfos;
  59. }
  60. const int len = read(fd, buffer, sizeof(buffer)-1);
  61. close(fd);
  62. if (len < 0) {
  63. LOGD("Unable to open process fd=%d", fd);
  64. return cpuInfos;
  65. }
  66. buffer[len] = 0;
  67. #else
  68. FILE* fp = fopen("fonts/stat-huawei.txt", "rb");
  69. if (fp == NULL)
  70. return cpuInfos;
  71. fread(buffer, sizeof(buffer)-1, 1, fp);
  72. fclose(fp);
  73. size_t len = strlen(buffer);
  74. #endif
  75. char* p = buffer;
  76. const char* end = p + len;
  77. char* next = NULL;
  78. int cpuIndex;
  79. const int COLUMN = sizeof(CpuInfo) / sizeof(long);
  80. size_t i = 0;
  81. while (readLine(p, end, &next))
  82. {
  83. // break if the line with no cpu prefix
  84. if (p[0] != 'c' || p[1] != 'p' || p[2] != 'u')
  85. break;
  86. // LOGD("%s\n", p);
  87. // Removes 'cpu%d' prefix
  88. p = p + 3;
  89. if (*p == ' ')
  90. { // The first line means the average cpu usage
  91. cpuIndex = 0;
  92. }
  93. else
  94. {
  95. cpuIndex = strtol(p, &p, 10) + 1;
  96. }
  97. // LOGD("cpu index: %d\n", cpuIndex);
  98. cpuInfos.resize(cpuIndex + 1);
  99. for (i = 0; i < COLUMN; ++i)
  100. {
  101. long value = strtol(p, &p, 10);
  102. // LOGD("%ld ", value);
  103. CpuInfo& info = cpuInfos[cpuIndex];
  104. long* e = (long*)&info + i;
  105. *e = value;
  106. }
  107. // LOGD("%s", "\n");
  108. p = next;
  109. }
  110. return cpuInfos;
  111. }
  112. void ProcessCpuTracker::update()
  113. {
  114. static const int JIFFYMILLIS = 10;
  115. std::vector<CpuInfo> cpuInfos = readProcStat();
  116. if (!cpuInfos.empty())
  117. {
  118. if (_cpuTimeInfos.size() < cpuInfos.size())
  119. {
  120. _cpuTimeInfos.resize(cpuInfos.size());
  121. }
  122. // LOGD("cpuInfo size: %d", (int)cpuInfos.size());
  123. for (size_t i = 0, len = cpuInfos.size(); i < len; ++i)
  124. {
  125. CpuTimeInfo& cpuTimeInfo = _cpuTimeInfos[i];
  126. const CpuInfo& cpuInfo = cpuInfos[i];
  127. // Total user time is user + nice time.
  128. const long usertime = (cpuInfo.userTime + cpuInfo.niceTime) * JIFFYMILLIS;
  129. // Total system time is simply system time.
  130. const long systemtime = cpuInfo.systemTime * JIFFYMILLIS;
  131. // Total idle time is simply idle time.
  132. const long idletime = cpuInfo.idleTime * JIFFYMILLIS;
  133. // Total irq time is iowait + irq + softirq time.
  134. const long iowaittime = cpuInfo.ioWaitTime * JIFFYMILLIS;
  135. const long irqtime = cpuInfo.irqTime * JIFFYMILLIS;
  136. const long softirqtime = cpuInfo.softIrqTime * JIFFYMILLIS;
  137. // This code is trying to avoid issues with idle time going backwards,
  138. // but currently it gets into situations where it triggers most of the time. :(
  139. if (false || (usertime >= cpuTimeInfo.mBaseUserTime && systemtime >= cpuTimeInfo.mBaseSystemTime
  140. && iowaittime >= cpuTimeInfo.mBaseIoWaitTime && irqtime >= cpuTimeInfo.mBaseIrqTime
  141. && softirqtime >= cpuTimeInfo.mBaseSoftIrqTime && idletime >= cpuTimeInfo.mBaseIdleTime)) {
  142. cpuTimeInfo.mRelUserTime = usertime - cpuTimeInfo.mBaseUserTime;
  143. cpuTimeInfo.mRelSystemTime = systemtime - cpuTimeInfo.mBaseSystemTime;
  144. cpuTimeInfo.mRelIoWaitTime = iowaittime - cpuTimeInfo.mBaseIoWaitTime;
  145. cpuTimeInfo.mRelIrqTime = irqtime - cpuTimeInfo.mBaseIrqTime;
  146. cpuTimeInfo.mRelSoftIrqTime = softirqtime - cpuTimeInfo.mBaseSoftIrqTime;
  147. cpuTimeInfo.mRelIdleTime = idletime - cpuTimeInfo.mBaseIdleTime;
  148. // if (true) {
  149. // LOGD("CPU%d, Total U: %ld, N:%ld S:%ld I:%ld W:%ld Q:%ld O:%ld\n",
  150. // (int)i,
  151. // cpuInfo.userTime,
  152. // cpuInfo.niceTime,
  153. // cpuInfo.systemTime,
  154. // cpuInfo.idleTime,
  155. // cpuInfo.ioWaitTime,
  156. // cpuInfo.irqTime,
  157. // cpuInfo.softIrqTime
  158. // );
  159. // LOGD("CPU%d, Rel U:%ld, S:%ld, I:%ld, Q:%ld\n",
  160. // (int)i,
  161. // cpuTimeInfo.mRelUserTime,
  162. // cpuTimeInfo.mRelSystemTime,
  163. // cpuTimeInfo.mRelIdleTime,
  164. // cpuTimeInfo.mRelIrqTime
  165. // );
  166. // if (cpuTimeInfo.mRelUserTime < 0
  167. // || cpuTimeInfo.mRelSystemTime < 0
  168. // || cpuTimeInfo.mRelIdleTime < 0
  169. // || cpuTimeInfo.mRelIrqTime < 0)
  170. // {
  171. // LOGD("CPU%d,base U:%ld, S:%ld, I:%ld, Q:%ld\n",
  172. // (int)i,
  173. // cpuTimeInfo.mBaseUserTime,
  174. // cpuTimeInfo.mBaseSystemTime,
  175. // cpuTimeInfo.mBaseIdleTime,
  176. // cpuTimeInfo.mBaseIrqTime
  177. // );
  178. // }
  179. // }
  180. cpuTimeInfo.mBaseUserTime = usertime;
  181. cpuTimeInfo.mBaseSystemTime = systemtime;
  182. cpuTimeInfo.mBaseIoWaitTime = iowaittime;
  183. cpuTimeInfo.mBaseIrqTime = irqtime;
  184. cpuTimeInfo.mBaseSoftIrqTime = softirqtime;
  185. cpuTimeInfo.mBaseIdleTime = idletime;
  186. } else {
  187. // if (usertime < cpuTimeInfo.mBaseUserTime)
  188. // {
  189. // LOGD("ERROR: usertime: %ld, base: %ld", usertime, cpuTimeInfo.mBaseUserTime);
  190. // }
  191. //
  192. // if (systemtime < cpuTimeInfo.mBaseSystemTime)
  193. // {
  194. // LOGD("ERROR: systemtime: %ld, base: %ld", systemtime, cpuTimeInfo.mBaseSystemTime);
  195. // }
  196. //
  197. // if (iowaittime < cpuTimeInfo.mBaseIoWaitTime)
  198. // {
  199. // LOGD("ERROR: iowaittime: %ld, base: %ld", iowaittime, cpuTimeInfo.mBaseIoWaitTime);
  200. // }
  201. //
  202. // if (irqtime < cpuTimeInfo.mBaseIrqTime)
  203. // {
  204. // LOGD("ERROR: irqtime: %ld, base: %ld", irqtime, cpuTimeInfo.mBaseIrqTime);
  205. // }
  206. //
  207. // if (softirqtime < cpuTimeInfo.mBaseSoftIrqTime)
  208. // {
  209. // LOGD("ERROR: softirqtime: %ld, base: %ld", softirqtime, cpuTimeInfo.mBaseSoftIrqTime);
  210. // }
  211. //
  212. // if (idletime < cpuTimeInfo.mBaseIdleTime)
  213. // {
  214. // LOGD("ERROR: idletime: %ld, base: %ld", idletime, cpuTimeInfo.mBaseIdleTime);
  215. // }
  216. if (usertime > 0 || idletime > 0)
  217. {
  218. cpuTimeInfo.mBaseUserTime = usertime;
  219. cpuTimeInfo.mBaseSystemTime = systemtime;
  220. cpuTimeInfo.mBaseIoWaitTime = iowaittime;
  221. cpuTimeInfo.mBaseIrqTime = irqtime;
  222. cpuTimeInfo.mBaseSoftIrqTime = softirqtime;
  223. cpuTimeInfo.mBaseIdleTime = idletime;
  224. }
  225. cpuTimeInfo.mRelUserTime = 0;
  226. cpuTimeInfo.mRelSystemTime = 0;
  227. cpuTimeInfo.mRelIoWaitTime = 0;
  228. cpuTimeInfo.mRelIrqTime = 0;
  229. cpuTimeInfo.mRelSoftIrqTime = 0;
  230. cpuTimeInfo.mRelIdleTime = 0;
  231. LOGD("CPU: %d, /proc/stats has gone backwards; skipping CPU update\n", (int)i);
  232. }
  233. }
  234. }
  235. }
  236. static long printRatio(std::stringstream& ss, long numerator, long denominator) {
  237. long hundreds = 0;
  238. if (denominator > 0)
  239. {
  240. long thousands = (numerator*1000)/denominator;
  241. hundreds = thousands/10;
  242. ss << hundreds;
  243. if (hundreds < 10) {
  244. long remainder = thousands - (hundreds*10);
  245. if (remainder != 0) {
  246. ss << '.';
  247. ss << remainder;
  248. }
  249. }
  250. }
  251. else
  252. {
  253. ss << '0';
  254. }
  255. ss << " ";
  256. return hundreds;
  257. }
  258. static long printProcessCPU(std::stringstream& ss, long totalTime, long user)
  259. {
  260. return printRatio(ss, user, totalTime);
  261. }
  262. void ProcessCpuTracker::printCurrentState()
  263. {
  264. std::stringstream ss;
  265. long totalCpuUsage = 0;
  266. for (size_t i = 0, len = _cpuTimeInfos.size(); i < len; ++i)
  267. {
  268. CpuTimeInfo& cpuTimeInfo = _cpuTimeInfos[i];
  269. const long totalTime = cpuTimeInfo.mRelUserTime + cpuTimeInfo.mRelSystemTime + cpuTimeInfo.mRelIoWaitTime
  270. + cpuTimeInfo.mRelIrqTime + cpuTimeInfo.mRelSoftIrqTime + cpuTimeInfo.mRelIdleTime;
  271. // if (totalTime <= 0)
  272. // {
  273. // LOGD("cjh totalTime, i=%d: %ld mRelUserTime: %ld, mRelSystemTime: %ld, mRelIoWaitTime: %ld, mRelIrqTime: %ld, mRelSoftIrqTime: %ld, mRelIdleTime: %ld",
  274. // (int)i,
  275. // totalTime,
  276. // cpuTimeInfo.mRelUserTime,
  277. // cpuTimeInfo.mRelSystemTime,
  278. // cpuTimeInfo.mRelIoWaitTime,
  279. // cpuTimeInfo.mRelIrqTime,
  280. // cpuTimeInfo.mRelSoftIrqTime,
  281. // cpuTimeInfo.mRelIdleTime
  282. // );
  283. // }
  284. const long preCoreUsage = printProcessCPU(ss, totalTime, cpuTimeInfo.mRelUserTime);
  285. if (i > 0)
  286. {
  287. totalCpuUsage += preCoreUsage;
  288. }
  289. }
  290. ss << "T:";
  291. ss << totalCpuUsage;
  292. std::string str = ss.str();
  293. LOGD("CPU: %s", str.c_str());
  294. }