linux Load Average 计算

在内核代码 kernel/sched/loadavg.c 中有一个公式:

a1 = a0 * e + a * (1 - e)


此算法是指数加权移动平均法(Exponential Weighted Moving Average,EMWA),是一种特殊的加权移动平均法,它考虑当前和历史的所有数据,强调当前样本的重要性,逐渐淡化历史样本的重要程度。EWMA的权重随着时间呈指数式递减,越靠近当前时刻的数值加权系数就越大。

其中a0是上一时刻的值,a1是当前时刻的值,e 是一个系数,取值范围是[0,1],a是当前时刻的某个指标采样值。

具体到linux load的计算,a0是上一时刻的load,a1是当前时刻的load,e是一个常量系数,a 是当前时刻的active的进程/线程数量。

linux 内核计算了三个load  值,分别是1分钟/5分钟/15分钟 load 。计算这三个load 值时,使用了三个不同的常量系数e,内核代码中定义如下:


#define FSHIFT        11        /* nr of bits of precision */
#define FIXED_1        (1<<FSHIFT)    /* 1.0 as fixed-point */
#define LOAD_FREQ    (5*HZ+1)    /* 5 sec intervals */
#define EXP_1        1884        /* 1/exp(5sec/1min) as fixed-point */
#define EXP_5        2014        /* 1/exp(5sec/5min) */
#define EXP_15        2037        /* 1/exp(5sec/15min) */

EXP_* 这三个值为以下计算出来:
    1884 = 2048/(power(e,(5/(60*1))))          /* e = 2.71828 */
    2014 = 2048/(power(e,(5/(60*5))))
    2037 = 2048/(power(e,(5/(60*15))))

    5是指每五秒采样一次,60是指每分钟60秒,1、5、15则分别是1分钟、5分钟和15分钟。

/**
 * calc_load - Load Average 计算
 *  @load : 上一时刻的load
 *  @exp  : 常量系数
 *  @active : active的进程/线程数量
 */
/* * a1 = a0 * e + a * (1 - e) */
static inline unsigned long calc_load(unsigned long load, unsigned long exp, unsigned long active)
{
    unsigned long newload;

    newload = load * exp + active * (FIXED_1 - exp);

    if (active >= load)
        newload += FIXED_1-1;

    return newload / FIXED_1;
}

/*
 * a1 = a0 * e + a * (1 - e)
 *
 * a2 = a1 * e + a * (1 - e)
 *    = (a0 * e + a * (1 - e)) * e + a * (1 - e)
 *    = a0 * e^2 + a * (1 - e) * (1 + e)
 *
 * a3 = a2 * e + a * (1 - e)
 *    = (a0 * e^2 + a * (1 - e) * (1 + e)) * e + a * (1 - e)
 *    = a0 * e^3 + a * (1 - e) * (1 + e + e^2)
 *
 *  ...
 *
 * an = a0 * e^n + a * (1 - e) * (1 + e + ... + e^n-1) [1]
 *    = a0 * e^n + a * (1 - e) * (1 - e^n)/(1 - e)
 *    = a0 * e^n + a * (1 - e^n)
 *
 * [1] application of the geometric series:
 *
 *              n         1 - x^(n+1)
 *     S_n := \Sum x^i = -------------
 *             i=0          1 - x
 */
static unsigned long
calc_load_n(unsigned long load, unsigned long exp,
        unsigned long active, unsigned int n)
{
    return calc_load(load, fixed_power_int(exp, FSHIFT, n), active);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值