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

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