(一)简介:
测试前取/sys/devices/system/cpu/cpufreq/policy4/stats/time_in_state(个cpu频点及运行时间: Documentation/cpu-freq/cpufreq-stats.txt)和/proc/stat(各cpu不同state的时间)数据,测试开始,测试程序sleep指定的测试时间,测试结束,再次获取测试结束时的节点数据,进行计算分析。
(二)编译及应用
-
测试cpu在各个频点的使用率,以及cpu的功耗
vendor/bin/power/cpu/loading # ./cpu_loading -t 60
- 源码路径:
vendor/****/proprietories-source/power/cpu
- 编译:
source build/envsetup.sh lunch cd vendor/****/proprietories-source/power/cpu mm (或mmm vendor/****/proprietories-source/power/cpu)
-
测试实例:
:/data/local/tmp # ./cpu_loading_androidq -t 60 || Testing ***** || testing 60s cpuN 768000 884000 1000000 1100000 1200000 online idle cpu0 9.06% 0.08% 0.08% 0.07% 2.31% 11.60% 88.40% cpu1 8.63% 0.07% 0.08% 0.06% 2.20% 11.05% 88.95% cpu2 7.16% 0.06% 0.06% 0.05% 1.83% 9.16% 90.84% cpu3 7.68% 0.07% 0.07% 0.06% 1.96% 9.83% 90.17% Freq 78.13% 0.67% 0.70% 0.58% 19.94% sum: 357529.68kHZ power: 10.93 cpuN 768000 1050000 1225000 1400000 1500000 1600000 online idle cpu4 5.39% 0.03% 0.04% 0.10% 0.05% 0.67% 6.29% 93.71% cpu5 3.25% 0.02% 0.02% 0.06% 0.03% 0.40% 3.79% 96.21% cpu6 2.58% 0.01% 0.02% 0.05% 0.03% 0.32% 3.01% 96.99% cpu7 2.88% 0.02% 0.02% 0.06% 0.03% 0.36% 3.36% 96.64% Freq 85.78% 0.48% 0.57% 1.67% 0.85% 10.65% sum: 144219.61kHZ power: 8.12 sum_total: 501749.29KHZ power_total: 19.05
(三)代码分析
- 数据提取 getCpuInfo()
以8核两簇(4大4小)为例,
cpuClass[cpuClassNum=0,1,2]=[0,4,8],即policy0/policy4/和cpu最大number cpu7;
getCpuInfo(CPU_INFO* cpuInfo):获取time_in_state节点信息,各个频点及对应的运行时间;
cpuInfo[cpuClass[i]].freq[k]/cpuInfo[cpuClass[i]].loading[k],保存了policy0、policy4的各freq频点和运行时间信息;
static CPU_INFO cpu_info_start[CPU_MAX_NUM]:记录测试开始时的信息
static CPU_INFO cpu_info_end[CPU_MAX_NUM]:记录测试结束时的信息
static CPU_INFO cpu_result_info[CPU_MAX_NUM]:记录计算结果信息# cat /sys/devices/system/cpu/cpufreq/policy0/stats/time_in_state 768000 1290 884000 26 1000000 38 1100000 24 1200000 1865 # cat /sys/devices/system/cpu/cpufreq/policy4/stats/time_in_state 768000 1128 1050000 107 1225000 61 1400000 100 1500000 58 1600000 3108 :/ #
保存了policy0、policy4的freq和loading信息到cpuInfo[0]和cpuInfo[4]中136 for(k = 0; k < CPU_MAX_FREQPOINT; k++){ 137 if(EOF == fscanf(fp,"%d",&cpuInfo[cpuClass[i]].freq[k])) break; 138 if(EOF == fscanf(fp,"%lld",&cpuInfo[cpuClass[i]].loading[k])) break; 139 DEBUG("%d %lld\n",cpuInfo[cpuClass[i]].freq[k],cpuInfo[cpuClass[i]].loading[k]); 140 }
对于policy0,把cpu0的cpuInfo[0]赋值给cpuInfo[0~3];对于policy4,把cpu4的cpuinfo[4]赋值给cpuInfo[4~7]
141 cpuInfo[cpuClass[i]].freqNum = k; 142 DEBUG("k= %d\n",k); 143 for(k = cpuClass[i]; k < cpuClass[i+1]; k++){ 144 cpuInfo[k] = cpuInfo[cpuClass[i]]; 145 DEBUG("cpuInfo[%d] : %lld\n",k,cpuInfo[k]); 146 }
保存/proc/stat中cpu数据到procStat[i],procStat[0]保存如下cpu行数据,其余保存到procStat[1~8].
kernel/sched/cputime.c
include/linux/kernel_stat.h
具体解释参考:https://blog.csdn.net/sinat_20184565/article/details/81571868:/ # cat proc/stat cpu 11078 9238 12157 9111734 2023 0 246 0 0 0 cpu0 1732 1628 2407 1136106 433 0 188 0 0 0 cpu1 1931 1419 2162 1137030 302 0 17 0 0 0 cpu2 1544 1516 1930 1137878 264 0 10 0 0 0 cpu3 1748 1351 1804 1138473 262 0 5 0 0 0 cpu4 1524 1008 1372 1139334 233 0 11 0 0 0 cpu5 1103 748 941 1140638 186 0 4 0 0 0 cpu6 557 1132 665 1141069 185 0 5 0 0 0 cpu7 936 433 872 1141203 154 0 2 0 0 0 intr 1451982 0 0 261185 0 229995 0 0 0 2803 0 0 0 39 51 5 4603 0 0 963 139337 0 0 0 0 0 0 25911 0 733 2757 79 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 0 0 0 0 0 0 414 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ctxt 1812766 btime 1573882097 processes 6161 procs_running 2 procs_blocked 0 softirq 816814 1 274241 5710 0 0 0 78514 220750 0 237598
取各个cpu的procStat[i].idle数据,保存到对应cpuInfo[i-1].cpuIdle;计算procStat[i].sumState,保存到对应cpuInfo[i-1].SumState213 cpuInfo[i-1].cpuIdle = procStat[i].idle; 214 procStat[i].sumState = procStat[i].user+procStat[i].nice+procStat[i].system+procStat[i].idle+ 215 procStat[i].iowait+procStat[i].irq+procStat[i].softirq+procStat[i].steal+procStat[i].guest+procStat[i].guest_nice; 216 cpuInfo[i-1].SumState = procStat[i].sumState; 217 DEBUG("cpu%dSum %ld\n",i-1,cpuInfo[i-1].SumState);
-
计算结果 getCpuResult()
计算测试时间段内/proc/stat节点cpuIdle和SumState差值,保存到cpuInfoResult[];
计算测试时间段内/sys/devices/system/cpu/cpufreq/policy4/stats/time_in_state节点cpu[0~7] 各频点运行时间(loading)差值;227 for(i = 0; i < cpuNum; i++){ 228 cpuInfoResult[i].ifOnline = cpuInfoStart[i].ifOnline; 229 cpuInfoResult[i].cpuIdle = cpuInfoEnd[i].cpuIdle-cpuInfoStart[i].cpuIdle; 230 cpuInfoResult[i].SumState = cpuInfoEnd[i].SumState-cpuInfoStart[i].SumState; 231 DEBUG("cpuInfoResult[%d].cpuIdle:%lld\n",i,cpuInfoResult[i].cpuIdle); 232 DEBUG("cpuInfoResult[%d].SumState:%lld\n",i,cpuInfoResult[i].SumState); 233 234 if(cpuInfoStart[i].freqNum != cpuInfoEnd[i].freqNum){ 235 return -1; 236 } 237 freqNum = cpuInfoResult[i].freqNum = cpuInfoStart[i].freqNum; 238 for(k = 0; k < freqNum; k++){ 239 if(cpuInfoStart[i].freq[k] != cpuInfoEnd[i].freq[k]){ 240 return -1; 241 } 242 cpuInfoResult[i].freq[k] = cpuInfoStart[i].freq[k]; 243 cpuInfoResult[i].loading[k] = cpuInfoEnd[i].loading[k]-cpuInfoStart[i].loading[k]; 244 }
-
数据打印 getCpuPrintInfo()
totalTime = cpu[7] time_in_state节点所有频点对应的时间(cpuInfoResult[i].loading,单位10ms)和;
cpuPrint[i].idlePercent = cpu i的cpuIdle/SumState;
cpuPrint[i].onlinePercent = 100-cpuPrint[i].idlePercent;
cpuPrint[i].freqPercent[k] = cpu i的cpuInfoResult[i].loading[k]*100/totalTime;263 for(i=0; i < cpuNum; i++){ 264 totalTime = 0; 265 266 for(k = 0; k <= cpuInfoResult[i].freqNum; k++){ 267 totalTime += cpuInfoResult[i].loading[k]; 268 } 269 if(totalTime < cpuInfoResult[i].cpuIdle){ 270 totalTime = cpuInfoResult[i].cpuIdle; 271 } 272 DEBUG("totalTime is: %lld\n",totalTime); 273 } 274 275 for(i = 0; i < cpuNum; i++){ 276 cpuPrint[i].ifOnline = cpuInfoResult[i].ifOnline; 277 if(!cpuPrint[i].ifOnline){continue;} 278 cpuPrint[i].idlePercent = (double)(cpuInfoResult[i].cpuIdle*100)/(cpuInfoResult[i].SumState); 279 cpuPrint[i].onlinePercent = 100-cpuPrint[i].idlePercent; 280 for(k = 0; k < cpuInfoResult[i].freqNum; k++){ 281 cpuPrint[i].freqPercent[k] = (double)(cpuInfoResult[i].loading[k]*100)/totalTime; 282 DEBUG("freq %0.2f%% \t",cpuPrint[i].freqPercent[k]); 283 } 284 DEBUG("\n"); 285 }
resultPrintf()
分别打印policy0和policy4各个cpu每个频点的使用率:
例如768MH:[1- idle/sum] *(freq_time/total_time)目前统计各个cpu某个频点使用率计算方法: [1- delta(cpuIdle)/delta(SumState)] *[delta(loading)/delta(totalTime)]=(proc/stat节点下idle占比)*(/sys/devices/system/cpu/cpufreq/policy*/stats/time_in_state该节点下该频点运行时间比) 次计算方法有误,cpu频点与idle无联系,cpu处在idle状态时,可运行在任意频点,不能正确反应cpu loading。 例如: 在10s测试时间内,cpu0在768MHZ频点运行4s,在1200MHZ运行6s;idle状态4s; 1)假设cpu0频率在768MHZ时都处在idle状态,cpu0 768MHZ使用率实际为0,1200MHZ使用率为60%; 2)假设cpu0频率在1200MHZ时其中4s处在idle状态,cpu0 768MHZ使用率为40%,1200MHZ使用率为20%; 按现在计算方法都为:768MHZ使用率为40%*60%=24%,1200MHZ使用率为%60*%60=36%,与实际数据不符。 同理,计算sum和power的方法也存在该问题。