关于Cgroup的简单测试


简单介绍Cgroup

(如果对cgroup熟悉可以忽略)

一般情况下,cgroup挂载到一个虚拟文件目录,然后可以通过文件系统的API对其操作。

># mount | grep cgroup 可以查看mount point

(debian) /sys/fs/cgroup/
(redhat) /cgroup/

以下非特殊说明,均以ubuntu12.04(3.5.0-23-generic) 为准

如果没有,安装方式

># apt-get install cgroup-bin

># yum -y install libcgroup

可以在 /proc/cgroups 下面看到目前有哪些子系统以及他们的使用情况

root@vm-222:/sys/fs/cgroup/blkio# cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset 9 1 1
cpu 10 10 1
cpuacct 11 1 1
memory 12 1 1
devices 13 1 1
freezer 14 1 1
blkio 15 2 1
perf_event 16 1 1

在 /sys/fs/cgroup/ 目录下可以看到如下子系统, 这是系统默认挂载方式,也是推荐的方式。

zhangbo3@vm-222:/sys/fs/cgroup$ ll
total 0
drwxr-xr-x 10 root root 200 Aug 31 23:06 ./
drwxr-xr-x 6 root root 0 Aug 31 23:14 ../
drwxr-xr-x 2 root root 0 Aug 31 23:06 blkio/
drwxr-xr-x 2 root root 0 Sep 6 10:22 cpu/
drwxr-xr-x 2 root root 0 Aug 31 23:06 cpuacct/
drwxr-xr-x 2 root root 0 Sep 6 10:22 cpuset/
drwxr-xr-x 2 root root 0 Aug 31 23:00 devices/
drwxr-xr-x 2 root root 0 Au 31 23:06 freezr/
drwxr-xr-x 2 root root 0 Aug 31 23:06 memor/
drwxr-xr-x 2 root root 0 Aug 31 23:06 perf_event/

也可以将 CPU, MEMORY 子系统都挂载到一个目录下.

mount -t cgroup -o cpu,memory cpu_mem_cg /sys/fs/cgroup/cpu_mem_cg

但是当CPU子系统已经被挂载过一次之后,就不能再挂载到第二个目录。

>#mount -t cgroup -o cpu,memory cpu_mem_cg /sys/fs/cgroup/cpu_mem_cg
提示错误如下:
>#mount: /sys/fs/cgroup/cpu_mem_cg already mounted or /sys/fs/cgroup/cpu_mem_cg busy

子系统文件介绍,以cpu子系统为例:

cpu
├── cgroup.clone_children
├── cgroup.event_control
├── cgroup.procs
├── cpu.cfs_period_us
├── cpu.cfs_quota_us
├── cpu.rt_period_us
├── cpu.rt_runtime_us
├── cpu.shares
├── cpu.stat
├── notify_on_release
├── release_agent
└── tasks

tasks 里面包含了当前进程,默认安装cgroup后,当前所有系统进程都会纳入cgroup管理,并且被加入到cgroup 根目录下,所有值为cgroup默认值,调度策略也使用完全公平调度.

cat tasks

可以看到所有进程.

cgroup 采用层级管理方式,可以在cpu子系统下面直接新建目录。

>#mkdir test

在test/ 目录下面,会基础根目录的所有属性,但是不包括tasks.

可以调整test/ 目录下面的cpu.* 的值对其设置,比如设置 cpu.shares=100

>#echo 100 > cpu.shares

所有tasks里面的pid都会在这个cgroup的管理下, 按照cpu.shares=100的值作为系统调度.

测试及验证

此次测试只针对CPU和blkio子系统,CPU用来限制CPU调度,blkio用来限制块设备IO调度

测试点

- 查看cpu.shares值是否符合调度预期
- mysql进程cpu调度是否符合预期
- 磁盘IO调度是否符合预期

实际测试结果

cpu.shares值是否符合预期

cpu.shares 值作为CPU的子系统的全局调度策略,为某个group设置cpu.shaes值后,会按照系统当前所有shares值为其分配一定权重,默认一个group最大值为1024, 这是个相对值, 比如group1, group2 的shares值同为100,他们应该获取相同的CPU时间片, 如果group1 设置为100,group2 设置为200,则group2的时间片应该是group1的两倍.

以一个会占据单核所有CPU的进程为例:

#include <stdlib.h>
#include <stdio.h>
int main(){
volatile float a;
while(1) {
a = 88888.8 * 88888.78;
}
return ;
}

默认所有进程已经加入cgroup豪华午餐.

由于是双核机器,开两个程,完全占据所有CPU.

PID  USER   PR  NI VIRT RES   SHR  S      %CPU %MEM  TIME+ COMMAND
39707 zhangbo3 20 0 4156 348 272 R 99 0.0 0:13.88 crazy
39863 zhangbo3 20 0 4156 352 272 R 99 0.0 0:36.14 crazy

四个进程

39863 zhangbo3  20   0  4156  352  272 R   48  0.0   1:38.10 crazy
39707 zhangbo3 20 0 4156 348 272 R 46 0.0 3:27.95 crazy
40124 zhangbo3 20 0 4156 352 272 R 43 0.0 0:05.55 crazy
4025 zhangbo3 20 0 4156 352 272 R 46 0.0 0:05.70 crazy

默认权值是1024的cgroup,进程几乎是平分CPU.

现将39863 39707 两个进程加入到test group, 并设置其cpu.shares=512

echo 39863 >> tasks

echo 39707 >> tasks

echo 512 >> cpu.shares

查看当前cpu利用率

40124 zhangbo3  20   0  4156  352  272 R   63  0.0   3:12.10 crazy
40125 zhangbo3 20 0 4156 352 272 R 61 0.0 3:12.02 crazy
39863 zhangbo3 20 0 4156 352 272 R 34 0.0 4:28.27 crazy
39707 zhangbo3 20 0 4156 348 272 R 32 0.0 6:12.77 crazy

可以看到, 39863 39707 两个进程的CPU 使用率基本是前两个的一半,完全符合预期有木有.

mysql进程cpu调度是否符合预期

将两个mysql实例加入到统一group下,为其设置cpu.shares=500

利用mysqlslap 对两个实例小小压测一下.

ps:针对CPU的压测,需要将CPU都压满才能体现cpu.shares的值的分配,如果是空载情况下,所有group都会最大限度的利用CPU.

User time 6.66, System time 13.08
Maximum resident set size 9548, Integral resident set size 0
Non-physical pagefaults 26115, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 253951, Involuntary context switches 5412
User time 6.57, System time 13.20
Maximum resident set size 9536, Integral resident set size 0
Non-physical pagefaults 26080, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 255336, Involuntary context switches 4518

可以观察到两者的Involuntary context switches值相差不大


将两个mysql 实例加入到不同的group下,分别为其设置cpu.shares=500, 1000

User time 12.07, System time 17.12
Maximum resident set size 150872, Integral resident set size 0
Non-physical pagefaults 938774, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 227545, Involuntary context switches 10615
User time 12.01, System time 18.79
Maximum resident set size 134212, Integral resident set size 0
Non-physical pagefaults 1087038, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 227556, Involuntary context switches 6800

可以观察到Involuntary context switches值基本符合预期

磁盘IO调度是否符合预期

分别将磁盘blkio.weight 设置为 500

dd if=/dev/zero of=/data2/dd.test bs=8k count=1024000

产生两个8.4G的文件

产生如下IO调度分配结果

1024000+0 records in
1024000+0 records out
8388608000 bytes (8.4 GB) copied, 84.7144 s, 99.0 MB/s
1024000+0 records in
1024000+0 records out
8388608000 bytes (8.4 GB) copied, 81.2984 s, 103 MB/s

看似符合预期,于是进行下一步

将进程1的IO权值设置为1000, 进程2的权值设置为100

可以看到两者并无差别,不符合我们的预期,是我打开的方式不对么?

4000+0 records in
4000+0 records out
4194304000 bytes (4.2 GB) copied, 5.292 s, 70.7 MB/s
4000+0 records in
4000+0 records out
4194304000 bytes (4.2 GB) copied, 60.3834 s, 69.5 MB/s

因为需要使用完全公平调度,于是设置io调度方式为cfq

echo cfq > /sys/block/<divice-name>/queue/scheduler

在cgroup文档里面有这么一个提示:

blkio子系统只针对非buffered IO或者read IO起作用.

使用直接IO方式启动DD

dd if=/dev/zero of=/data/dd.test oflag=direct,nonblock bs=1M count=4000

将buffer刷到磁盘,并清掉cache

sync
echo 3 > /proc/sys/vm/drop_caches

观察到IO调度符合预期.

8192000+0 records in
8192000+0 records out
4194304000 bytes (4.2 GB) copied, 35.9584 s, 117 MB/s root@ip-172-17-6-225:/tmp# cat cgroup2.log
4000+0 records in
4000+0 records out
4194304000 bytes (4.2 GB) copied, 97.82 s, 42.9 MB/s

因为进程1提前结束,所以会让出一部分时间片给进程2,但是从iotop来看,同时运行的情况下IO调度是负荷预期的.

总结使用BLKIO子系统必须满足以下几个条件:

1. 默认系统调度方式为CFQ, 完全公平调度
2. 内核编译宏 CONFIG_BLK_CGROUP=y CONFIG_CFQ_GROUP_IOSCHED=y
3. 必须是非buffered 写 IO

总结

测试过程中使用到的命令:

mysql 压力测试
mysqlslap -uxxx -pxxx -P 6810 -h127.0.0.1 --concurrency=200 --iterations=1 --auto-generate-sql --number-of-queries=20000 --debug-info --create-schema='test2' --auto-generate-sql-load-type=mixed dd 磁盘压测
dd if=/dev/zero of=/data/dd.test oflag=direct,nonblock bs=1M count=4000 iotop 查看IO情况

本次测试针对CPU和IO调度都做了相应的测试,调度参数符合预期.

针对cgroup对MySQL的管理方案:

  1. 限制 CPU 使用,每个MySQL实例一个group, 并为其设置合适的cpu.shares值
  2. 限制 blkio 使用,并打开 Innodb_flush_method=O_DIRECT
  3. 使用 device 子系统限制,如果占用空间过大,可以设置group对特定块设备不可写

参考文献

RedHat Cgroup Documents

Blkio 子系统内核参数

Mysql InnoDB IO configuration and flushing

Linux资源管理-IO优先级

A expanded CFQ scheduler for cgroups

[原] Cgroup CPU, Blkio 测试的更多相关文章

  1. 多核CPU利用测试

      一直在想程序上是否特意让线程在指定的CPU上去运行,这样可以提高运行效率,所以特地写个代码让CPU使用率画正弦曲线的实验,我使用的是AMD X4 641的CPU,为四核四线程的片子. 代码如下 # ...

  2. Android CPU耗电量测试

    Android CPU耗电量测试 在测试Android app时,不仅仅要关注app的功能,也好关注app的性能指标,cpu.内存.流量.电量等.简单介绍下电量测试中的cpu耗电. 影响耗电的因素 C ...

  3. cpu压力测试

    一.cpu压力测试 1.安装stress软件 sudo apt-get install stress #加压 nohup stress --cpu 8 & #查看cpu负载 top

  4. C#关于反序列化实例时,接收实体字段少于或大于原实体对象 解析测试

    在项目中总会用到son解析,比如RabbitMQ中使用json串解析,比如发过来的实体对象有50个字段,而实际只需要用到里面的几个字段,这时我们创建实体时,只需要创建需要的几个字段即可. 测试实例,首 ...

  5. 【原】cpu消耗高,查看对应的线程栈信息

    在压测过程中,有时候cpu会飙升,造成这种现象的原因很多, 可能是gc造成的,也可能是某个方法造成的, 如果从找对应的方法入手,下面简单罗列下步骤: 1.top,获取pid 下面cpu消耗90%左右 ...

  6. cpu 满载测试软件

    for i in `seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l)`; do dd if=/dev/zero of=/d ...

  7. ubuntu tensorflow cpu faster-rcnn 测试自己训练的模型

    (flappbird) luo@luo-All-Series:~/MyFile/tf-faster-rcnn_box$ (flappbird) luo@luo-All-Series:~/MyFile/ ...

  8. CPU压力测试--限制到指定范围

    作用:增加CPU使用率到指定范围 1.书写shell脚本增加CPU压力 #! /bin/bash # filename cputest.sh endless_loop() { echo -ne &qu ...

  9. (原)C++中测试代码执行时间

    转载请注明出处(不过这个用法网上到处都是): http://www.cnblogs.com/darkknightzh/p/4987738.html LARGE_INTEGER nFreq, nBegi ...

随机推荐

  1. Fis3前端工程化之项目实战

    Fis3项目 项目目录结构: E:. │ .gitignore │ fis-conf.js │ index.html │ package.json │ README.md │ ├─material │ ...

  2. 日期格式代码出现两次的错误 ORA-01810

    错误的原因是使用了两次MM . 一.Oracle中使用to_date()时格式化日期需要注意格式码 如:select to_date('2005-01-01 11:11:21','yyyy-MM-dd ...

  3. 阿里云直播 C# SDK 如何使用

    阿里云直播SDK的坑 1.直播云没有单独的SDK,直播部分被封装在CDN的相关SDK当中. 2.针对SDK,没有相关Demo. 3.针对SDK,没有相关的文档说明. 4.针对SDK的说明,官网上的说明 ...

  4. Connect() 2016 大会的主题 ---微软大法好

    文章首发于微信公众号"dotnet跨平台",欢迎关注,可以扫页面左面的二维码. 今年 Connect 大会的主题是 Big possibilities. Bold technolo ...

  5. myeclipse学习总结一(在MyEclipse中设置生成jsp页面时默认编码为utf-8编码)

    1.每次我们在MyEclispe中创建Jsp页面,生成的Jsp页面的默认编码是"ISO-8859-1".在这种情况下,当我们在页面中编写的内容存在中文的时候,就无法进行保存.如下图 ...

  6. 06.LoT.UI 前后台通用框架分解系列之——浮夸的图片上传

    LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...

  7. 10个最好用的HTML/CSS 工具、插件和资料库

    大家在使用HTML/CSS开发项目的过程中,有使用过哪些工具,插件和库?下面介绍的10种HTML/CSS工具,插件和资料库,是国外程序员经常用到的. Firebug Lite FirebugLite ...

  8. Android数据加密之Base64编码算法

    前言: 前面学习总结了平时开发中遇见的各种数据加密方式,最终都会对加密后的二进制数据进行Base64编码,起到一种二次加密的效果,其实呢Base64从严格意义上来说的话不是一种加密算法,而是一种编码算 ...

  9. javascript匹配各种括号书写是否正确

    今天在codewars上做了一道题,如下 看上去就是验证三种括号各种嵌套是否正确书写,本来一头雾水,一种括号很容易判断, 但是三种怎么判断! 本人只是个前端菜鸟,,不会什么高深的正则之类的. 于是,在 ...

  10. jdb调试scala代码的简单介绍

    在linux调试C/C++的代码需要通过gdb,调试java代码呢?那就需要用到jdb工具了.关于jdb的用法在网上大家都可以找到相应的文章,但是对scala进行调试的就比较少了.其实调试的大致流程都 ...