CPU-PnP工具(一): cpu_loading

(一)簡介:

測試前取/sys/devices/system/cpu/cpufreq/policy4/stats/time_in_state(個cpu頻點及運行時間: Documentation/cpu-freq/cpufreq-stats.txt)和/proc/stat(各cpu不同state的時間)數據,測試開始,測試程序sleep指定的測試時間,測試結束,再次獲取測試結束時的節點數據,進行計算分析。

(二)編譯及應用

  1. 測試cpu在各個頻點的使用率,以及cpu的功耗

    vendor/bin/power/cpu/loading # ./cpu_loading -t 60
  2. 源碼路徑:
    vendor/****/proprietories-source/power/cpu
     
  3. 編譯:
    source build/envsetup.sh
    lunch
    cd vendor/****/proprietories-source/power/cpu
    mm
    (或mmm vendor/****/proprietories-source/power/cpu)
  4. 測試實例:

    :/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
    

     

(三)代碼分析

  1. 數據提取 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].SumState

    213             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);

     

  2. 計算結果 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         }

     

  3. 數據打印 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- \Deltaidle/\Deltasum] *(\Deltafreq_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的方法也存在該問題。

參考文檔:http://www.blogjava.net/fjzag/articles/317773.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章