理解PELT算法最重要的是理解负载贡献的计算方法。
1.物理时间被分为了1024us。即一个统计的周期(period)
2.如果统计的周期不足1024us被补齐。
3.每经历一个周期需要衰减1次,衰减系数为y。
我们常常看到给出的公式:
L = L0 + L1 * y + L2 * y^2 + L3 * y^3 + ... + Ln * y^n 公式1
L0表示当前周期,不需要衰减。
L1表示前1个周期的负载。
Ln表示前n个周期的负载。
linux内核给出的公式:
d1 d2 d3
^ ^ ^
| | |
|<->|<----------------->|<--->|
... |---x---|------| ... |------|-----x (now)
p-1
u' = (u + d1) y^p + 1024 \Sum y^n + d3 y^0
n=1
= u y^p + (Step 1)
p-1
d1 y^p + 1024 \Sum y^n + d3 y^0 (Step 2)
n=1
公式2
假设上一时刻负载贡献是u,经历d时间后的负载贡献如何计算呢?根据上面的例子,我们可以把时间d分成3和部分:d1是离当前时间最远(不完整的)period 的剩余部分,d2 是完整period时间,而d3是(不完整的)当前 period 的剩余部分。假设时间d是经过p个周期(d=d1+d2+d3, p=1+d2/1024)。d1,d2,d3 的示意图如上。
公式1和公式2是相等的。用来计算负载总和。
公式2中的step1是用来计算之前的负载衰减总和。step2用来计算当前的负载衰减。
很明显step1比较简单。step2比较复杂一些,因为需要展开求和。
下面是step2的计算函数:
static u32 __accumulate_pelt_segments(u64 periods, u32 d1, u32 d3)
{
u32 c1, c2, c3 = d3; /* y^0 == 1 */
/*
* c1 = d1 y^p
*/
c1 = decay_load((u64)d1, periods);
/*
* p-1
* c2 = 1024 \Sum y^n
* n=1
*
* inf inf
* = 1024 ( \Sum y^n - \Sum y^n - y^0 )
* n=0 n=p
*/
c2 = LOAD_AVG_MAX - decay_load(LOAD_AVG_MAX, periods) - 1024;
return c1 + c2 + c3;
}
此函数的参数是periods为公式2中的p,d1和d3可以对应起来。
这里主要看c2如何计算:
在linux中最大负载贡献定义为了LOAD_AVG_MAX
参考:
CFS调度器(4)-PELT(per entity load tracking)CFS调度器-PELThttp://www.wowotech.net/process_management/450.htmlper-entity load tracking一、为何需要per-entity load tracking?http://www.wowotech.net/process_management/PELT.html