(一)簡介:
測試前取/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的方法也存在該問題。