ProcessCpuTracker.cpp 11 KB

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