博客首页 注册 建议与交流 排行榜 加入友情链接         宝宝相册的专门空间
推荐 投诉 搜索: 帮助

hutuworm

不覺碧山暮 秋雲暗幾重
  hutuworm.cublog.cn

关于作者
姓名: hutuworm
职业: OPS
年龄: 28
位置: Hangzhou
个性介绍: No idea.
|| << >> ||
我的分类


Linux问答:平均负载是怎样炼成的?

谷歌拼音盗用搜狗拼音词库事件,前段时间可谓闹得沸沸扬扬。搜狗拼音开发工程师那一篇《搜狗拼音输入法词库是怎样炼成的》写得深入浅出、荡气回肠,令我等搜狗拼音粉丝们深感搜狗词库来之不易,谷歌窃桃之举可鄙之极。为了表示对搜狗拼音的一贯支持,本文还是照例用搜狗拼音撰写。

言归正传。最近某个应用产品团队突然提出要增加数十台服务器,让兄弟我大出了一身冷汗。现在机架空间紧张的很,我们预算也有限,怎么能你说加几十台服务器就给加几十台?为什么?凭什么?给个理由先?对方回答,说是根据最近一段时间对其应用集群平均负载的观察结果,以及运营方面预估的访问量增长趋势数据,得出要加几十台服务器的结论。那么问题来了,且不论运营方面怎么预估访问量增长,用当前的平均负载作为基数来估算服务器增长,靠谱么?

我们首先来看看平均负载(Load Average)到底是什么?这个问题似乎从未有人清楚地阐释过,我也只知道所谓平均负载,就是指当前Running和Runnable队列里的任务总数摊到每个逻辑CPU的平均数。貌似多数UNIX/Linux教材、书籍里谈到平均负载这个概念时,都是这么忽悠人的,甚至讲的比前面这句更为含糊。幸好Linux Kernel开放源码,我们既然碰到了问题,就不妨做个愣头青,直接去源码里找找答案。

仔细一找,果然发现 kernel/timer.c 里这段疑似代码:


/*
 * calc_load - given tick count, update the avenrun load estimates.
 * This is called while holding a write_lock on xtime_lock.
 */

static inline void calc_load(unsigned long ticks)
{
        unsigned long active_tasks; /* fixed-point */
        static int count = LOAD_FREQ;

        count -= ticks;
        if (unlikely(count < 0)) {
                active_tasks = count_active_tasks();
                do {
                        CALC_LOAD(avenrun[0], EXP_1, active_tasks);
                        CALC_LOAD(avenrun[1], EXP_5, active_tasks);
                        CALC_LOAD(avenrun[2], EXP_15, active_tasks);
                        count += LOAD_FREQ;
                } while (count < 0);
        }
}


又在 include/linux/sched.h 里找到了 CALC_LOAD 宏定义:

#define FSHIFT 11 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
#define LOAD_FREQ (5*HZ) /* 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) */

#define CALC_LOAD(load,exp,n) \
        load *= exp; \
        load += n*(FIXED_1-exp); \
        load >>= FSHIFT;


看不懂了。本着“内事不决问老婆,外事不决问Google”的原则,还是Google一下。果然有位大仙,法号 Dr. Gunther ,曾专门撰写了一系列文章来研究这个 Load Average 的算法,及其背后的险恶用心:

1. The "LA Triplets" Quiz

2. UNIX® Load Average Part 1: How It Works

3. UNIX® Load Average: An Addendum

4. UNIX® Load Average Part 2: Not Your Average Average

5. UNIX® Load Average Reweighed

略过各篇文章前面深深浅浅的描述和数学公式,只看最后的Summary或者Conclusion,我们就可以发现:

所谓负载(load),并非如我们想像的那样,表示系统的利用率,而只是反映CPU run_queue 的长度。这三个数字(1/5/15-min LA)只是三个不同时间序列的时点抽样,还是经指数阻尼平滑的平均数,而且它们是在以错误的顺序反映趋势信息。

既然平均负载(Load Average)的算法都不靠谱,那么以此为基数的估算又怎么可能不是扯淡呢?

发表于: 2007-04-20,修改于: 2007-04-21 23:22,已浏览1110次,有评论4条 推荐 投诉


网友评论
网友: xiaosuo 时间:2007-04-21 16:41:57 IP地址:221.238.129.★
That said, the degree of error between the two different expressions for the weighting factors is much less than 1% as Mathematica demonstrates. 
你所帖的参考连接中的作者并没有说Linux所采用的计算1分钟Load Average的方法和“正确”的方法相比,数学结果有显著差异,相反,他们之间的误差小于1%。

网友: hutuworm 时间:2007-04-21 19:06:54 IP地址:219.82.114.★
Only the 1-minute load average calculation is significantly affected.

您可能漏看了最后一句。

网友: xiaosuo 时间:2007-04-21 22:39:42 IP地址:221.238.129.★
那个是Magic Number被“相当大”地影响了(1890和1884的区别),并且是和5分和15分的(5分和15分的结果相同)进行比较,最终结果的相对误差还是相当小的。

网友: hutuworm 时间:2007-04-21 23:21:28 IP地址:219.82.114.★
再仔细看了一遍,阻尼系数问题确实不足以支持LA缺乏可信度之论点,故删去第2点。谢谢xiaosuo同学指正! :)

 发表评论