RT-Thread Nano 环境下 CPU占用率统计方法。
编者:张永辉 2021年5月25日
说明:自创方法,统计CPU使用率
代码: PRJ_0_RTT_nano_FinSH_cpu usage
--------------------------------------------------------------------------------
理论:
1 CPU空闲时总是运行idle线程,开启外挂后,idle会不停的调用外挂钩子
2 首次调用hook时,
关闭任务切换,计算A变量加到1百万需要使用的tick数。比如用了500个tick这么久。cpu_min_cnt = 500
3 然后每次调用hook时,
开启任务切换,计算B变量加到1百万需要使用的tick数。比如用了620个tick, cpu_run_cnt = 620
在B自加期间,有自行其他任务,所以本次的tick当然会大于500,
多出的tick数,则是CPU不空间的占用时间
4 计算CPU占用率
比如CPU用了620个周期中,其中120个周期是其他任务占用了的,所以cpu_usage= (620-500)/620=19.35%
5 关键代码
A B变量的自加过程必须一样,否则不具备可比性,比如本文中两个代码如下:
【A】
rt_enter_critical();
tick_tmp = rt_tick_get();
while(++cpu_min_cnt < CPU_CNT) {} //CPU耗时
cpu_min_cnt = rt_tick_get() - tick_tmp;
rt_exit_critical();
【B】
tick_tmp = rt_tick_get();
while(++cpu_run_cnt < CPU_CNT) {} //CPU耗时
cpu_run_cnt = rt_tick_get() - tick_tmp;
区别仅仅是是否有任务切换
6 实际效果,
RT_TICK_PER_SECOND =1000, GD32F405运行在120M时的 CPU占用率约 0.1%
LED任务中加入1个 a=0;while(++a<100000); 的耗时操作后,CPU占用率约 10.2%
LED任务中加入2个 a=0;while(++a<100000); 的耗时操作后,CPU占用率约 19.7%
LED任务中加入4个 a=0;while(++a<100000); 的耗时操作后,CPU占用率约 26.8%
7 不足:本方法统计周期不是1秒,而是变量加到CPU_CNT的为止的时间,CPU_CNT值越大,统计时间越长就越准确.
如果其他任务CPU占用到90%,统计时间将延长9倍。
8 也还有改进之处,,欢迎大家指点。
--------------------------------------------------------------------------------
1 rtconfig.h 中使能 RT_USING_HOOK宏定义,开启系统钩子功能。
2 board.c 的rt_hw_board_init
调用初始化函数borad_cpu_usage_init();
3 添加两个文件到工程
[broad_cpu_usage.h]
#ifndef __BROAD_CPU_USAGE_H__
#define __BROAD_CPU_USAGE_H__
void borad_cpu_usage_init(void);
int board_cpu_usage_get(char *major, char *minor);
void cpu_usage_idle_hook(void);
#endif
[broad_cpu_usage.c]
#include "gd32f10x_it.h"
#include <rtthread.h>
//****
#define CPU_CNT 5000000
int cpu_min_cnt = 0; //变量加CPU_CNT次,需要的最小tick数
int cpu_run_cnt = 0; //变量加CPU_CNT次,运行了的tick数
int cpu_usage = 0; //CPU占用率,,千分之N
void cpu_usage_idle_hook(void);
//初始化,rt_hw_board_init 调用
void borad_cpu_usage_init(void)
{
rt_thread_idle_sethook(cpu_usage_idle_hook);
}
//获取CPU占用率 (千分之N)
int board_cpu_usage_get(char *major, char *minor)
{
return cpu_usage;
}
//IDLE外挂函数,CPU空闲时会被实时调用
void cpu_usage_idle_hook(void)
{
rt_tick_t tick_tmp = rt_tick_get();
//将rt_ticks 从0加到RT_TICK_MAX,,需要的tick数
if(cpu_min_cnt==0)
{
rt_enter_critical(); //关闭CPU切换,但是sys_tick是没有关闭的
tick_tmp = rt_tick_get();
while(++cpu_min_cnt < CPU_CNT) {} //CPU耗时
cpu_min_cnt = rt_tick_get() - tick_tmp; //统计占用了的最小ticks数
rt_exit_critical();
}
//实时运行
cpu_run_cnt = 0;
tick_tmp = rt_tick_get();
while(++cpu_run_cnt < CPU_CNT) {} //CPU耗时
cpu_run_cnt = rt_tick_get() - tick_tmp; //运行期间,占用了的tick数
//计算占用率
cpu_usage = ((cpu_run_cnt - cpu_min_cnt)*1000 )/cpu_run_cnt; //使用整数表示. 50/1000 = 5%的占用率
rt_kprintf("cpu_usage = %d/1000\r\n" , cpu_usage);
}
4 编译运行即可。