美文网首页
Linux load average 辨析

Linux load average 辨析

作者: jhttroy | 来源:发表于2018-11-21 16:58 被阅读35次

    读取系统 load average

    uptime 或者 top 可以显示系统的 load average. 比如:

    [root@localhost ~]# uptime
     15:54:04 up 106 days,  6:35,  7 users,  load average: 1.45, 1.76, 2.02
    

    三个数字分别表示1,5,15分钟的数据。

    load average 中的 load

    load average 显示的并不是cpu 使用百分比。这也许是最容易产生的误解。这个误解有两方面的问题:

    1. load average 并非指 cpu load average 而是 system load average。远古时代(1993年之前)的确是指cpu load,也就是统计系统中处于 runnable 的线程。后来uninterruptible 的线程被计入统计,为了同时体现 I/O 或者 lock 的 wait 情况,此种情况系统并没有真正的 idle。此后这个指标的名字就由 cpu load average 改成了 system load average。
    2. 并非百分比,而是所有非 idle 线程的总数。需要提醒的是该数字并没有对系统核数做归一化,如果系统中有48个核而你看到的 load average 是20,那么系统基本是比较轻松的。也许当数值突破50之后才会感到压力山大,当然 it depends。

    load average 中的 average

    这个 average 并不是真的 average,而是采用一种指数阻尼的算法。Linux 引入了一些 magic number 简化计算。直接上代码:

    // include/linux/sched/loadavg.h
    
    #define FSHIFT          11              /* nr of bits of precision */
    #define FIXED_1         (1<<FSHIFT)     /* 1.0 as fixed-point */
    /* 每5秒采样一次 */
    #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) */
    
    /* n 表示 active task 的数量,也就是非 idle 线程的数量 */
    #define CALC_LOAD(load,exp,n) \
            load *= exp; \
            load += n*(FIXED_1-exp); \
            load >>= FSHIFT;
    
    extern void calc_global_load(unsigned long ticks);
    
    // kernel/sched/loadavg.c
    
    /*
     * calc_load - update the avenrun load estimates 10 ticks after the
     * CPUs have updated calc_load_tasks.
     *
     * Called from the global timer code.
     */
    void calc_global_load(unsigned long ticks)
    {
            unsigned long sample_window;
            long active, delta;
    
            sample_window = READ_ONCE(calc_load_update);
            if (time_before(jiffies, sample_window + 10))
                    return;
    
            /*
             * Fold the 'old' NO_HZ-delta to include all NO_HZ cpus.
             */
            delta = calc_load_nohz_fold();
            if (delta)
                    atomic_long_add(delta, &calc_load_tasks);
    
            active = atomic_long_read(&calc_load_tasks);
            active = active > 0 ? active * FIXED_1 : 0;
    
            avenrun[0] = calc_load(avenrun[0], EXP_1, active);
            avenrun[1] = calc_load(avenrun[1], EXP_5, active);
            avenrun[2] = calc_load(avenrun[2], EXP_15, active);
    
            WRITE_ONCE(calc_load_update, sample_window + LOAD_FREQ);
    
            /*
             * In case we went to NO_HZ for multiple LOAD_FREQ intervals
             * catch up in bulk.
             */
            calc_global_nohz();
    }
    

    直观的讲,如果之前系统一直处于 idle 状态,在单核系统下增加一个100% load 的线程,一分钟之后的 load average (1min) 为 0.62 而不是线性 average 的结果 1。


    Load average experiment to visualize exponential damping

    参考

    http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html

    相关文章

      网友评论

          本文标题:Linux load average 辨析

          本文链接:https://www.haomeiwen.com/subject/nkscqqtx.html