一篇讲解CPU性能指标提取及源码分析

内容简介

这篇报告主要根据CPU性能指标——运行队列长度、调度延迟和平均负载,对系统的性能影响进行简单分析。


运行队列长度

CPU调度程序运行队列中存放的是那些已经准备好运行、正等待可用CPU的轻量级进程,如果准备运行 的轻量级进程数超过系统所能处理的上限,运行队列就会很长,运行队列长表明系统负载可能已经饱和。

代码源于参考资料1中map.c用于获取运行队列长度的部分代码:

// 获取运行队列长度
// SEC("kprobe/update_rq_clock")
int update_rq_clock(struct pt_regs *ctx) {
u32 key = 0;
u32 rqKey = 0;
struct rq *p_rq = 0;
p_rq = (struct rq *)rq_map.lookup(&rqKey);
if (!p_rq) { // 针对map表项未创建的时候,map表项之后会自动创建并初始化
return 0;
}
bpf_probe_read_kernel(p_rq, sizeof(struct rq), (void *)PT_REGS_PARM1(ctx));
u64 val = p_rq->nr_running;
runqlen.update(&key, &val);
return 0;
}

挂载点:update_rq_clock()函数

update_rq_clock()被scheduler_tick()函数调用。

周期性调度器:

周期性调度器在scheduler_tick中实现. 如果系统正在活动中, 内核会按照频率HZ自动调用该函数. 如果没有进程在等待调度, 那么在计算机电力供应不足的情况下, 内核将关闭该调度器以减少能耗. 这对于我们的 嵌入式设备或者手机终端设备的电源管理是很重要的。

周期性调度器主流程:

scheduler_tick函数定义在kernel/sched/core.c,linux内核版本:5.15:

void scheduler_tick(void)
{
int cpu = smp_processor_id();
struct rq *rq = cpu_rq(cpu);
struct task_struct *curr = rq->curr;
struct rq_flags rf;
unsigned long thermal_pressure;
u64 resched_latency;
arch_scale_freq_tick();
sched_clock_tick();
rq_lock(rq, &rf);
update_rq_clock(rq);
.....

在这个函数中主要做两方面工作:

1.更新相关统计量,管理内核中的与整个系统和各个进程的调度相关的统计量. 其间执行的主要操作 是对各种计数器+1。

2.激活负责当前进程调度类的周期性调度方法。

由于调度器的模块化结构, 主体工程其实很简单, 在更新统计信息的同时, 内核将真正的调度工作委 托给了特定的调度类方法。

内核先找到了就绪队列上当前运行的进程curr, 然后调用curr所属调度类sched_class的周期性调度 方法task_tick,即:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值