Sample: Use cgroup cpu subsystem to control cpu usage

来源:互联网 发布:苹果mac没有声音 音频 编辑:程序博客网 时间:2024/06/10 22:20

使用cgroup限制CPU使用的例子

原文:hanjianqiao.github.io

通过cgroup控制CPU使用

1、首先看一个例子:

// file: loop_count.c#include <stdio.h>#include <stdlib.h>#include <unistd.h>int forker(int nprocesses){    pid_t pid;    if(nprocesses > 0)    {        if ((pid = fork()) < 0)        {            perror("fork");        }        else if (pid == 0)        {            //Child stuff here            //printf("Child %d end\n", nprocesses);        }        else if(pid > 0)        {            //parent            forker(nprocesses - 1);        }    }    return nprocesses;}int main(int argc, char **argv){    int count = 100000000;    int loop = 0;    int nchild = 5;    if(argc > 1){        nchild = atoi(argv[1]);    }    forker(nchild);    int id = getpid();    while(1){        for(int i = 0; i < count; i++){            // do nothing        }        printf("id %d loop: %d\n", id, loop++);    }    return 0;}

编译运行(我用的服务器是4核,所以开3个子线程):

gcc loop_count.c./a.out 3

输出,可以看到四个线程的计数刚开始基本一致,慢慢有一些差值。
image

运行top命令,查看cpu使用情况:
image

完美!可以看到4个核心均被占满,没个线程基本上使用到了100%的CPU。

再看一下运行8个线程(2x核心数)的情况:
8个线程均分CPU资源,每个线程占约50%。
image

image

2、如果线程数不是CPU核心整数倍

gcc loop_count.c./a.out 5

看一下输出和top信息:
image

image

可见,内核依然尽力均分CPU资源。但是毕竟平均能力有限,还是有比较大的误差的。

3、如果我们想要各个线程还是使用相同的CPU,有什么办法呢?

cgroup!

启动6个线程:

gcc loop_count.c./a.out 5

打开新的终端,运行下面的命令:

# 需要使用root权限su# 新建cpuset子控制组foomkdir /sys/fs/cgroup/cpuset/foo# 该组可以使用CPU核心:0、1和2echo 0,1,2 > /sys/fs/cgroup/cpuset/foo/cpuset.cpus# 这个是必要的,这里先不解释echo 0 > /sys/fs/cgroup/cpuset/foo/cpuset.mems# 将运行的6个线程加入到foo控制组里面,格式echo PID > cgroup_pathecho 23931 > /sys/fs/cgroup/cpuset/foo/tasksecho 23932 > /sys/fs/cgroup/cpuset/foo/tasksecho 23933 > /sys/fs/cgroup/cpuset/foo/tasksecho 23934 > /sys/fs/cgroup/cpuset/foo/tasksecho 23935 > /sys/fs/cgroup/cpuset/foo/tasksecho 23936 > /sys/fs/cgroup/cpuset/foo/tasks

有意思的事情发生了:
image

每个线程都占50%CPU,而且CPU3空闲。

4、更精确的控制

上面,我们使得每个CPU核心运行相同的任务,以达到平均的CPU使用率。更进一步,我们可以使用cgroup提供的另一个功能实现:

gcc loop_count.c./a.out 5

打开新的终端,运行下面的命令:

# 需要使用root权限su# 下面,为每个线程建立一个控制组,每个控制组可使用30%的CPU# 新建cpuset子控制组foo# thread 0mkdir /sys/fs/cgroup/cpu/foo0echo 1000000 > /sys/fs/cgroup/cpu/foo0/cpu.cfs_period_usecho 300000 > /sys/fs/cgroup/cpu/foo0/cpu.cfs_quota_usecho 24187 > /sys/fs/cgroup/cpu/foo0/tasks# thread 1mkdir /sys/fs/cgroup/cpu/foo1echo 1000000 > /sys/fs/cgroup/cpu/foo1/cpu.cfs_period_usecho 300000 > /sys/fs/cgroup/cpu/foo1/cpu.cfs_quota_usecho 24188 > /sys/fs/cgroup/cpu/foo1/tasks# thread 2mkdir /sys/fs/cgroup/cpu/foo2echo 1000000 > /sys/fs/cgroup/cpu/foo2/cpu.cfs_period_usecho 300000 > /sys/fs/cgroup/cpu/foo2/cpu.cfs_quota_usecho 24189 > /sys/fs/cgroup/cpu/foo2/tasks# thread 3mkdir /sys/fs/cgroup/cpu/foo3echo 1000000 > /sys/fs/cgroup/cpu/foo3/cpu.cfs_period_usecho 300000 > /sys/fs/cgroup/cpu/foo3/cpu.cfs_quota_usecho 24190 > /sys/fs/cgroup/cpu/foo3/tasks# thread4mkdir /sys/fs/cgroup/cpu/foo4echo 1000000 > /sys/fs/cgroup/cpu/foo4/cpu.cfs_period_usecho 300000 > /sys/fs/cgroup/cpu/foo4/cpu.cfs_quota_usecho 24191 > /sys/fs/cgroup/cpu/foo4/tasks# thread5mkdir /sys/fs/cgroup/cpu/foo5echo 1000000 > /sys/fs/cgroup/cpu/foo5/cpu.cfs_period_usecho 300000 > /sys/fs/cgroup/cpu/foo5/cpu.cfs_quota_usecho 24192 > /sys/fs/cgroup/cpu/foo5/tasks

image

虽然方法有些笨拙,但可以看到CPU占用率控制在30%左右。

总结

cgroup可以比较方便精确地控制线程的CPU占用率,更多的cgroup细节可以参考相关内核文档,我的博客也会继续做一些补充。