Android CPU使用率:top和dump cpuinfo的不同
2016-07-06 13:49
543 查看
CPU是系统非常重要的资源,在Android中,查看CPU使用情况,可以使用top命令和dump cpuinfo。我记得很久以前,就发现这两者存在不同,初步猜测应该是算法上存在差异。最近需要采集应用CPU的使用率,看了一下两种CPU的计算方法。
CPU的计算是proc->delta_time * 100 / total_delta_time。
先看total_delta_time由:
而这些变量的值,是在read_procs通过读取/proc/stat的jiffies得到:
而proc->delta_time是两次读取/proc/pid/stat相减得到:
可见,top是一段时间内,计算process的cpu jiffies与总的cpu jiffies差值得到。
而printProcessCPU输出process CPU的使用情况:
user+system+iowait+irq+softIrq 比totalTime。
看下st个变量的赋值,在collectStats里面:
st.rel_utime 和 st.rel_stime还是通过读/proc/pid/stat相减得到,而st.rel_uptime却是通过 SystemClock.uptimeMillis()差值,并不是跟top一样,通过得到总CPU jiffies。
看到这,也就能明白,top跟dump cpuinfo的区别在于:top分母有的是总测CPU jiffies,而dump cpuinfo是uptime,是时间,而并非jiffies,也能解释为什么top出来的cpu,大部分时间会比dump cpuinfo的原因。
1、top
top是比较经典的CPU计算方法,top的代码在androidm/system/core/toolbox/top.c下面,输出process的cpu使用率在print_procs里面:<code class="hljs haskell has-numbering"><span class="hljs-title">static</span> void print_procs(void) { ... for (i = <span class="hljs-number">0</span>; i < num_new_procs; i++) { <span class="hljs-keyword">if</span> (new_procs[i]) { old_proc = find_old_proc(new_procs[i]->pid, new_procs[i]->tid); <span class="hljs-keyword">if</span> (old_proc) { new_procs[i]->delta_utime = new_procs[i]->utime - old_proc->utime; new_procs[i]->delta_stime = new_procs[i]->stime - old_proc->stime; } <span class="hljs-keyword">else</span> { new_procs[i]->delta_utime = <span class="hljs-number">0</span>; new_procs[i]->delta_stime = <span class="hljs-number">0</span>; } new_procs[i]->delta_time = new_procs[i]->delta_utime + new_procs[i]->delta_stime; } } total_delta_time = (new_cpu.utime + new_cpu.ntime + new_cpu.stime + new_cpu.itime + new_cpu.iowtime + new_cpu.irqtime + new_cpu.sirqtime) - (old_cpu.utime + old_cpu.ntime + old_cpu.stime + old_cpu.itime + old_cpu.iowtime + old_cpu.irqtime + old_cpu.sirqtime); ... <span class="hljs-title">if</span> (!threads) { printf(<span class="hljs-string">"%5d %2d %3"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"%% %c %5d %6"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"K %6"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"K %3s %-8.8s %s\n"</span>, <span class="hljs-keyword">proc</span>->pid, <span class="hljs-keyword">proc</span>->prs, <span class="hljs-keyword">proc</span>->delta_time * <span class="hljs-number">100</span> / total_delta_time, <span class="hljs-keyword">proc</span>->state, <span class="hljs-keyword">proc</span>->num_threads, <span class="hljs-keyword">proc</span>->vss / <span class="hljs-number">1024</span>, <span class="hljs-keyword">proc</span>->rss * getpagesize() / <span class="hljs-number">1024</span>, <span class="hljs-keyword">proc</span>->policy, user_str, <span class="hljs-keyword">proc</span>->name[<span class="hljs-number">0</span>] != <span class="hljs-number">0</span> ? <span class="hljs-keyword">proc</span>->name : <span class="hljs-keyword">proc</span>->tname); } <span class="hljs-keyword">else</span> { printf(<span class="hljs-string">"%5d %5d %2d %3"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"%% %c %6"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"K %6"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"K %3s %-8.8s %-15s %s\n"</span>, <span class="hljs-keyword">proc</span>->pid, <span class="hljs-keyword">proc</span>->tid, <span class="hljs-keyword">proc</span>->prs, <span class="hljs-keyword">proc</span>->delta_time * <span class="hljs-number">100</span> / total_delta_time, <span class="hljs-keyword">proc</span>->state, <span class="hljs-keyword">proc</span>->vss / <span class="hljs-number">1024</span>, <span class="hljs-keyword">proc</span>->rss * getpagesize() / <span class="hljs-number">1024</span>, <span class="hljs-keyword">proc</span>->policy, user_str, <span class="hljs-keyword">proc</span>->tname, <span class="hljs-keyword">proc</span>->name); } ... } </code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li></ul>
CPU的计算是proc->delta_time * 100 / total_delta_time。
先看total_delta_time由:
<code class="hljs avrasm has-numbering"> total_delta_time = (new_cpu<span class="hljs-preprocessor">.utime</span> + new_cpu<span class="hljs-preprocessor">.ntime</span> + new_cpu<span class="hljs-preprocessor">.stime</span> + new_cpu<span class="hljs-preprocessor">.itime</span> + new_cpu<span class="hljs-preprocessor">.iowtime</span> + new_cpu<span class="hljs-preprocessor">.irqtime</span> + new_cpu<span class="hljs-preprocessor">.sirqtime</span>) - (old_cpu<span class="hljs-preprocessor">.utime</span> + old_cpu<span class="hljs-preprocessor">.ntime</span> + old_cpu<span class="hljs-preprocessor">.stime</span> + old_cpu<span class="hljs-preprocessor">.itime</span> + old_cpu<span class="hljs-preprocessor">.iowtime</span> + old_cpu<span class="hljs-preprocessor">.irqtime</span> + old_cpu<span class="hljs-preprocessor">.sirqtime</span>)<span class="hljs-comment">;</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>
而这些变量的值,是在read_procs通过读取/proc/stat的jiffies得到:
<code class="hljs perl has-numbering">static void read_procs(void) { ... proc_dir = <span class="hljs-keyword">opendir</span>(<span class="hljs-string">"/proc"</span>); <span class="hljs-keyword">if</span> (!proc_dir) <span class="hljs-keyword">die</span>(<span class="hljs-string">"Could not open /proc.\n"</span>); new_procs = calloc(INIT_PROCS * (threads ? THREAD_MULT : <span class="hljs-number">1</span>), sizeof(struct proc_info <span class="hljs-variable">*)</span>); num_new_procs = INIT_PROCS * (threads ? THREAD_MULT : <span class="hljs-number">1</span>); file = fopen(<span class="hljs-string">"/proc/stat"</span>, <span class="hljs-string">"r"</span>); <span class="hljs-keyword">if</span> (!file) <span class="hljs-keyword">die</span>(<span class="hljs-string">"Could not open /proc/stat.\n"</span>); fscanf(file, <span class="hljs-string">"cpu <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span>"</span>, &new_cpu.<span class="hljs-keyword">utime</span>, &new_cpu.ntime, &new_cpu.stime, &new_cpu.itime, &new_cpu.iowtime, &new_cpu.irqtime, &new_cpu.sirqtime); fclose(file);</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul>
而proc->delta_time是两次读取/proc/pid/stat相减得到:
<code class="hljs haskell has-numbering"><span class="hljs-title">static</span> int read_stat(char *filename, struct proc_info *<span class="hljs-keyword">proc</span>) { ... /* <span class="hljs-type">Scan</span> rest <span class="hljs-keyword">of</span> string. */ sscanf(close_paren + <span class="hljs-number">1</span>, <span class="hljs-string">" %c "</span> <span class="hljs-string">"%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "</span> <span class="hljs-string">"%"</span> <span class="hljs-type">SCNu64</span> <span class="hljs-string">"%"</span> <span class="hljs-type">SCNu64</span> <span class="hljs-string">"%*d %*d %*d %*d %*d %*d %*d "</span> <span class="hljs-string">"%"</span> <span class="hljs-type">SCNu64</span> <span class="hljs-string">"%"</span> <span class="hljs-type">SCNu64</span> <span class="hljs-string">"%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "</span> <span class="hljs-string">"%d"</span>, &<span class="hljs-keyword">proc</span>->state, &<span class="hljs-keyword">proc</span>->utime, &<span class="hljs-keyword">proc</span>->stime, &<span class="hljs-keyword">proc</span>->vss, &<span class="hljs-keyword">proc</span>->rss, &<span class="hljs-keyword">proc</span>->prs); return <span class="hljs-number">0</span>; }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li></ul>
可见,top是一段时间内,计算process的cpu jiffies与总的cpu jiffies差值得到。
2、dump cpuinfo
dump cpuinfo是Android特有的命令(我一直都android的各种dump、trace非常感兴趣,快玩物丧志了。。。)。dump cpuinfo命令的实现在androidm/frameworks/base/core/java/com/android/internal/os/ProcessCpuTracker.java类里面,方法是printCurrentState:<code class="hljs avrasm has-numbering">final public String printCurrentState(long now) { ... int N = mWorkingProcs<span class="hljs-preprocessor">.size</span>()<span class="hljs-comment">;</span> for (int i=<span class="hljs-number">0</span><span class="hljs-comment">; i<N; i++) {</span> Stats <span class="hljs-keyword">st</span> = mWorkingProcs<span class="hljs-preprocessor">.get</span>(i)<span class="hljs-comment">;</span> printProcessCPU(pw, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.added</span> ? <span class="hljs-string">" +"</span> : (<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.removed</span> ? <span class="hljs-string">" -"</span>: <span class="hljs-string">" "</span>), <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.pid</span>, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.name</span>, (int)<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_uptime, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_utime, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_stime, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_minfaults, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_majfaults)<span class="hljs-comment">;</span> if (!<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.removed</span> && <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.workingThreads</span> != null) { int M = <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.workingThreads</span><span class="hljs-preprocessor">.size</span>()<span class="hljs-comment">;</span> for (int j=<span class="hljs-number">0</span><span class="hljs-comment">; j<M; j++) {</span> Stats <span class="hljs-keyword">tst</span> = <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.workingThreads</span><span class="hljs-preprocessor">.get</span>(j)<span class="hljs-comment">;</span> printProcessCPU(pw, <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.added</span> ? <span class="hljs-string">" +"</span> : (<span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.removed</span> ? <span class="hljs-string">" -"</span>: <span class="hljs-string">" "</span>), <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.pid</span>, <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.name</span>, (int)<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_uptime, <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.rel</span>_utime, <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.rel</span>_stime, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>)<span class="hljs-comment">;</span> } } } ... }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li></ul>
而printProcessCPU输出process CPU的使用情况:
<code class="hljs cs has-numbering"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printProcessCPU</span>(PrintWriter pw, String prefix, <span class="hljs-keyword">int</span> pid, String label, <span class="hljs-keyword">int</span> totalTime, <span class="hljs-keyword">int</span> user, <span class="hljs-keyword">int</span> system, <span class="hljs-keyword">int</span> iowait, <span class="hljs-keyword">int</span> irq, <span class="hljs-keyword">int</span> softIrq, <span class="hljs-keyword">int</span> minFaults, <span class="hljs-keyword">int</span> majFaults) { pw.print(prefix); <span class="hljs-keyword">if</span> (totalTime == <span class="hljs-number">0</span>) totalTime = <span class="hljs-number">1</span>; printRatio(pw, user+system+iowait+irq+softIrq, totalTime); ... }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>
user+system+iowait+irq+softIrq 比totalTime。
看下st个变量的赋值,在collectStats里面:
<code class="hljs avrasm has-numbering">private int[] collectStats(String statsFile, int parentPid, boolean first, int[] curPids, ArrayList<Stats> allProcs) { int[] pids = Process<span class="hljs-preprocessor">.getPids</span>(statsFile, curPids)<span class="hljs-comment">;</span> ... final long uptime = SystemClock<span class="hljs-preprocessor">.uptimeMillis</span>()<span class="hljs-comment">;</span> final long[] procStats = mProcessStatsData<span class="hljs-comment">;</span> if (!Process<span class="hljs-preprocessor">.readProcFile</span>(<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.statFile</span><span class="hljs-preprocessor">.toString</span>(), PROCESS_STATS_FORMAT, null, procStats, null)) { continue<span class="hljs-comment">;</span> } ... if (DEBUG) Slog<span class="hljs-preprocessor">.v</span>(<span class="hljs-string">"Load"</span>, <span class="hljs-string">"Stats changed "</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.name</span> + <span class="hljs-string">" pid="</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.pid</span> + <span class="hljs-string">" utime="</span> + utime + <span class="hljs-string">"-"</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_utime + <span class="hljs-string">" stime="</span> + stime + <span class="hljs-string">"-"</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_stime + <span class="hljs-string">" minfaults="</span> + minfaults + <span class="hljs-string">"-"</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_minfaults + <span class="hljs-string">" majfaults="</span> + majfaults + <span class="hljs-string">"-"</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_majfaults)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_uptime = uptime - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_uptime<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_uptime = uptime<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_utime = (int)(utime - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_utime)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_stime = (int)(stime - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_stime)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_utime = utime<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_stime = stime<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_minfaults = (int)(minfaults - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_minfaults)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_majfaults = (int)(majfaults - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_majfaults)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_minfaults = minfaults<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_majfaults = majfaults<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.working</span> = true<span class="hljs-comment">;</span> ... }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li></ul>
st.rel_utime 和 st.rel_stime还是通过读/proc/pid/stat相减得到,而st.rel_uptime却是通过 SystemClock.uptimeMillis()差值,并不是跟top一样,通过得到总CPU jiffies。
看到这,也就能明白,top跟dump cpuinfo的区别在于:top分母有的是总测CPU jiffies,而dump cpuinfo是uptime,是时间,而并非jiffies,也能解释为什么top出来的cpu,大部分时间会比dump cpuinfo的原因。
相关文章推荐
- 【WWDC2016 Session笔记】 iOS 10 UICollectionView新特性
- Android spannableStringBuilder用法整理
- UE4实现描边效果
- UE4实现描边效果
- Longest Common Subsequence & Substring & prefix
- 超越之MongDB系列教程(十)MongDB_VUE工具使用(完)
- iOS NSDictionary里的keysSortedByValueUsingSelector排序使用
- Java并发包:阻塞队列(BlockingQueue)
- requestLayout() improperly called by android.widget.GridView{43cefbd VFED.VC.. .F...... 0,0-2190,319
- LeetCode刷题系列(十二)Quick Questions
- Context.managedQuery()和context.getContentResolver()获取Cursor关闭注意事项
- Ueditor在php中上传至七牛
- Error:Execution failed for task ':***:compileDebugAidl'.finished with non-zero exit value 3
- STL_Deque
- 使用pyquery碰到的问题
- ElasticSearch 全文检索 termQuery和queryString
- GCC内联函数:__builtin_types_compatible_p
- GCC内联函数:__builtin_types_compatible_p
- GCC内联函数:__builtin_types_compatible_p
- Android Studio中build.gradle文件详解