概述

今天,想尝试复现一个问题,需要达到一个效果就是将 CPU 打满,制造一个负载很高的情况,我的第一想法就是使用 stress,结果发现居然一直都打不满,只能打到一半(50%)就到顶了,所以就探索了一下什么问题,顺便记录一下。

操作过程

首先,我先看了一下这台机器上有几个核,总共有几个线程,然后以对应线程数量去启动 stress:

  1. [root@liqiang.io]# cat /proc/cpuinfo | grep "core id" | wc -l
  2. 6
  3. [root@liqiang.io]# cat /proc/cpuinfo | grep "processor" | wc -l
  4. 6

这里需要看的是逻辑核心数(线程数),实际上物理核是 6 个,每个核的线程数是 1 个,所以总共需要 6 个,没问题。接着就是启动 stress 了:

  1. [root@liqiang.io]# stress -c 6

然后就看到 CPU 使用率是这样的:

图 1:stress cpu 使用率

这就很厉害了,可以看到其实 stress 只占用了一个 core,然后使用率就是只有一个 100%,并没有达到我的预期,然后我就像,我多开两个不就行了,然后又开了一个 terminal,再跑一个,结果就变成这样了:

图 2:多开 stress cpu 使用率

你看他们,波澜不惊,继续平分,多么气人。那么这是什么问题呢?为什么会另开 terminal 也会跑到同一个 core 里面去呢,这应该有一些猫腻。

问题定位

所以我的怀疑方向是有同事限制了 shell 的 cgroup,导致我只能用固定的 core,于是我就先看看 stress 的 cgroup 是啥:

  1. [root@liqiang.io]# cat /proc/5813/cgroup
  2. 11:perf_event:/
  3. 10:cpuset:/zbs/app
  4. 9:devices:/system.slice/sshd.service
  5. 8:freezer:/
  6. 7:pids:/
  7. 6:blkio:/system.slice/sshd.service
  8. 5:net_prio,net_cls:/
  9. 4:hugetlb:/
  10. 3:cpuacct,cpu:/system.slice/sshd.service
  11. 2:memory:/system.slice/sshd.service
  12. 1:name=systemd:/system.slice/sshd.service

ok,从这里可以看到使用的 cpuset 是一个叫做 /zbs/app 的 cgroup 项,那再一步看看具体是怎么限制的:

  1. [root@liqiang.io]# cat /etc/cgconfig.conf | grep -A 7 zbs/app
  2. group zbs/app {
  3. cpuset {
  4. cpuset.cpus = "4,5";
  5. cpuset.mems = "0";
  6. cpuset.cpu_exclusive = "0";
  7. cpuset.mem_hardwall = "1";
  8. }
  9. }

可以看到是被限制到了 cpu 4 和 5 上了,对照一下 top 的 cpu 使用率看是否吻合:

图 3:详细的 cpu 使用率

ok,看上去就是这个问题,那么我要将 CPU 打满的话, 最简单的处理方式就是去掉这个 cgroup 限制就好了,但是这不太友好,所以更友好的方式应该是单独过滤我的 stress 进程,其他的照旧。