平均负载

性能优化 2019-04-07 3291 字 1276 浏览 点赞

当系统性能变低时(俗称卡顿),我们可以从平均负载入手,找到引发根源,然后解决。

什么是平均负载?

单位时间内,系统中处于可运行状态不可中断状态的平均进程数。

对上述状态释义如下:

  • 可运行状态进程:正在使用 CPU 、或是正在等待 CPU 的进程。用命令 ps 看到 STAT 为 R (Running,Runable)。
  • 不可中断状态进程:不可以被中断的进程,如等待硬件设备的I/O响应。用命令 ps 看到 STAT 为 D(Uninterruptible Sleep,也叫 Disk Sleep)。

    如何查看平均负载?

可用命令 uptime

Guan@Orchard:~$ uptime
 22:11:31 up 222 days, 23:10,  1 user,  load average: 0.00, 0.04, 0.01

可以看到 load average 后面有三个数值,分别表示前 1 分钟,前 5 分钟和前 15 分钟的平均负载。

如果假设当前平均负载为 2 ,则意味着:

  • 在只有 2 个 CPU 的系统上,所有 CPU 刚好沾满;
  • 在只有 1 个 CPU 的系统上,有一半的进程竞争不到 CPU;
  • 在有 4 个 CPU 的系统上,CPU 有 50% 的空闲。

这里建议:当平均负载高于 CPU 数量的 70% 时,应该开始分析排查负载高的问题。

查看系统 CPU 数量的方法:grep "model name" /proc/cpuinfo | wc -l

平均负载!=CPU使用率

当我们发现电脑卡顿,一般会马上去看 CPU 使用率,通常 top 命令,或者 htop 。事实上,我们还可以看平均负载,因为过高的负载也会造成机器性能下降。需要说明的是:$平均负载 != CPU 使用率$。

CPU 使用率是指:单位时间内 CPU 繁忙情况的统计。而平均负载不但包括正在使用 CPU 的进程,还包括等待 CPU 的进程,以及等待 I/O 的进程

二者关系可分三种情况讨论:

  • CPU密集型进程:使用大量 CPU 会导致平均负载升高,此时二者一致;
  • I/O密集型进程:等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
  • 大量进程:大量等待 CPU 的进程调度会导致平均负载升高,此时 CPU 使用率也会比较高。

Python 实验

以下用 Python 程序模拟 CPU 密集,I/O 密集,大量进程等待调度三种情况。都基于腾讯的学生优惠套餐服务器,也就是 1 核 2G 那种。


第一种情况:CPU 密集

# CPU 密集型
def test_func():
    # 死循环,自增 1
    x = 0
    while True:
        x += 1

test_func()

跑上段代码前,可以先使用 top ,方便观察 CPU 使用率; watch -d uptime 方便观察平均负载的变化。

在我的服务器上,CPU 很快飙到 99%+ ,一段时间后平均负载也上升到了 1.00+ 。

# top 命令
%Cpu(s): 99.7 us,  0.3 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

# uptime 命令
23:16:25 up 223 days, 15 min,  4 users,  load average: 1.05, 0.91, 0.61

即:使用大量 CPU 会导致平均负载升高,正确。


第二种情况:I/O 密集

# I/O密集型
import os
import time
import random
from threading import Thread

def test_func():
    while True:
        filename = ".{}-{}".format(int(time.time()), random.randrange(10000))
        with open(filename, "w+") as f:
            f.write("*" * 1000)
            f.flush()
            print(f.read())

for __ in range(50):
    t = Thread(target=test_func)
    t.start()
else:
    t.join()

为使效果明显,我开了很多线程,并且都在以“死循环”的方式的做I/O操作。此时在我的服务器上,CPU 使用率只是略有升高,而平均负载飙到了 39+ 。

# I/O 密集
%Cpu(s):  3.6 us, 13.1 sy,  0.0 ni,  0.0 id, 83.2 wa,  0.0 hi,  0.0 si,  0.0 st

# uptime 命令
23:45:41 up 223 days, 44 min,  4 users,  load average: 39.26, 14.98, 6.30

即:等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高,正确。


第三种情况:大量进程

# 大量进程
import time
from multiprocessing import Process

def test_func():
    while True:
        x = 0
        x += 1

for __ in range(50):
    p = Process(target=test_func)
    p.start()
else:
    p.join()

此次也开启了 50 个进程,通过 top 可以看到,尽管每个 python 带起来的进程只占用很少的 CPU ,这里清一色是 2.2% 。最后结果是 CPU 上升至 100% ,前1 分钟的平均负载达到了 49+ 。

# uptime 命令
00:04:24 up 223 days,  1:03,  4 users,  load average: 49.71, 28.25, 13.58

即:大量等待 CPU 的进程调度会导致平均负载、CPU 使用率升高,正确。

感谢

倪朋飞老师建议用 pidstatmpstat 作为性能分析工具,但因我的环境问题,暂时没装上,但 topuptime 也够看个大概了。



本文由 Guan 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论