前言
因为笔者面试中被问到了这个问题,感觉自己不是很清楚,所以还是整理一下,博客中也有不少讲到top
命令的,但是几乎没看到有把load average
这个讲清楚的,所以还是有必要来篇水文。
进入正题
由于这里只是分析load average
,具体怎么使用top
,大家应该都有所了解,我这里就不再赘述,重点分析一下load average
.
我们都知道load average
分别代表最近一分钟、最近5分钟、最近15分钟的负载。但是有的负载值才0.01
,有的负载值可以到1
,有的甚至可以到5
.这到底是什么意思呢?当负载数大于1的时候是不是就预示着系统负载很高?是不是疑惑中又夹杂着一点喜悦呢?因为你马上就要知道”谜底“了。开个玩笑,嘿嘿!
1.先查看一下cpu核数
我这里使用的是阿里云的centos7
cat /proc/cpuinfo |grep "cpu core"|wc -l
2
2.看一下是否开启超线程
cat /proc/cpuinfo | grep "processor" | wc -l
2
显然没有开启超线程,因为cpu线程数和cpu核数相同。
3.开始测试
public class Top {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
while(true){
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while(true){
}
}
}).start();
}
}
启动两个线程一直做空轮询,然后通过top
查看发现一分钟左右load average
第一个参数停留在1.98
左右,后面两位数字也在慢慢上升。
启动一个线程试一下。
public class Top {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
while(true){
}
}
}).start();
}
}
一分钟左右查看top:
top - 12:39:03 up 42 days, 14:15, 2 users, load average: 1.03, 0.63, 0.38
最近一分钟左右的负载基本稳定在1
左右,正好是2线程同时运行时的一半。
是不是可以下结论说:linux top的load average
和cpu核数有关,满负载的值就是cpu的个数呢?其实也不能完全这么说,因为还是load average
大于cpu核数的情况,再来做个试验,起5个线程:
for(int i=0;i<5;i++){
new Thread(new Runnable() {
public void run() {
while(true){
}
}
}).start();
}
大概运行了1-2分钟,top查看一下:
top - 12:49:24 up 42 days, 14:25, 2 users, load average: 4.96, 2.39, 1.18
Tasks: 76 total, 1 running, 75 sleeping, 0 stopped, 0 zombie
%Cpu0 : 99.7/0.3 100[||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||]
%Cpu1 : 99.3/0.7 100[||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||]
KiB Mem : 3881920 total, 921592 free, 2109728 used, 850600 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 1531428 avail Mem
发现负载基本上就稳定为5
了。可知load average
和线程数基本相等。
更深一层
static int loadavg_proc_show(struct seq_file *m, void *v)
{
unsigned long avnrun[3];
get_avenrun(avnrun, FIXED_1/200, 0);
seq_printf(m, "%lu.%02lu %lu.%02lu %lu.%02lu %ld/%d %d\n",
LOAD_INT(avnrun[0]), LOAD_FRAC(avnrun[0]),
LOAD_INT(avnrun[1]), LOAD_FRAC(avnrun[1]),
LOAD_INT(avnrun[2]), LOAD_FRAC(avnrun[2]),
nr_running(), nr_threads,
idr_get_cursor(&task_active_pid_ns(current)->idr) - 1);
return 0;
}
这是top输出到控制台的代码,发现数据是从avnrun
数组中取出来的,找到数组avnrun
赋值的地方:
if (!time_before(jiffies, sample_window + 10)) {
/*
* Catch-up, fold however many we are behind still
*/
delta = jiffies - sample_window - 10;
n = 1 + (delta / LOAD_FREQ);
active = atomic_long_read(&calc_load_tasks);
active = active > 0 ? active * FIXED_1 : 0;
avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
WRITE_ONCE(calc_load_update, sample_window + n * LOAD_FREQ);
}
找到calc_load_n(avenrun[0], EXP_1, active, n)
就大致明白了load average
的值和当前执行的任务数有关,具体atomic_long_read
方法内的逻辑,其实没必要关心,有兴趣的可以自行查看。
结论
Linux top命令的load average
满负荷是cpu核心的个数,实际上应该比满负荷的值要小,不然会影响性能。如果负载超过cpu核心数的话,则说明系统超负荷运行。而负载最大值和并发执行的线程数有关,大小基本和并发执行的线程数一致。有了对load average
的大致了解后,就可以判断出系统的性能状况,好做出相应的调整。现在来回答开篇提到的那个问题是否load average大于1(小于2)就是系统负载比较高
就非常容易了。首先要看一下cpu的核数和线程数,如果是单核CPU,负载等于1就是满负荷运转了,如果是四核、甚至更多核心的CPU,负载大于1这说明系统当前负载很小,不需要过多关心。文中如果有什么错误的地方,还请提出,谢谢~