cgroup还有其他一些限制特性,如io,pid,hugetlb等,这些用处不多,参见Cgroupv1。下面介绍下与系统性能相关的io和hugepage,cgroup的io介绍参考Cgroup - Linux的IO资源隔离

linux IO

linux io涉及到对文件(磁盘设备)的读写性能,对io的优化主要分为

  • 磁盘相关参数调优
  • 文件系统参数调优,一般为io调度器选择和调度器参数调优
  • 文件系统挂载(mount)参数调优

使用如下命令查看当前系统支持的调度器

# dmesg | grep -i scheduler
[ 1.343756] io scheduler noop registered
[ 1.343759] io scheduler deadline registered (default)
[ 1.343784] io scheduler cfq registered
[ 1.343787] io scheduler mq-deadline registered
[ 1.343789] io scheduler kyber registered

使用如下命令查看当前磁盘支持的调度器,方括号表示当前生效的调度器

#  cat /sys/block/sda/queue/scheduler
noop [deadline] cfq

调度器的参数位于/sys/block/sda/queue/iosched/

Noop:该算法实现了最简单的FIFO队列,所有I/O请求大致按照先来后到的顺序进行操作,特别适用于固态硬盘

  • 在IO调度器下方有更加智能的IO调度设备。如果您的Block Device Drivers是Raid,或者SAN,NAS等存储设备,这些设备会更好地组织IO请求,不用IO调度器去做额外的调度工作;
  • 上层应用程序比IO调度器更懂底层设备。或者说上层应用程序到达IO调度器的IO请求已经是它经过精心优化的,那么IO调度器就不需要画蛇添足,只需要按序执行上层传达下来的IO请求即可。
  • 对于一些非旋转磁头氏的存储设备,使用Noop的效果更好。因为对于旋转磁头式的磁盘来说,IO调度器的请求重组要花费一定的CPU时间,但是对于SSD磁盘来说,这些重组IO请求的CPU时间可以节省下来,因为SSD提供了更智能的请求调度算法,不需要内核去画蛇添足。这篇文章提及了SSD中使用Noop效果会更好。

CFQ:给所有进程分配等同的块设备使用的时间片,进程在时间片内,可以将产生的IO请求提交给块设备进行处理,时间片结束,进程的请求将排进它自己的队列,等待下次调度的时候进行处理,适用于通用服务器。

Deadline:保证每个IO请求在一定的时间内一定要被服务到,以此来避免某个请求饥饿,deadline在大多数多线程应用场景和数据库应用场景下表现的性能要优于cfq

可以通过直接修改/sys/block/sda/queue/scheduler文件来临时修改调度器类型,永久修改可以参考如下命令

grubby --grub --update-kernel=ALL --args="elevator=deadline"

deadline使用了3个队列,”standerd queue“中按照block号排序,”read FIFO”和“write FIFO“则按照request请求的顺序添加,read FIFO的超时时间为500ms,write FIFO的超时时间为5s。系统会按照顺序处理standerd queue中的请求,当read FIFO或write FIFO超时后会切换到对应的FIFO处理request。这种处理方式用于防止”request starvation“,即系统可能会在某个block上处理多个request,而导致其他block上的request超时。更多详情参见Kernel Korner - I/O Schedulers,需要注意的是Anticipatory I/O Scheduler已经被废弃。

在遇到系统读写过慢时,可以采用如下步骤进行定位。(注:该系统的模拟故障由dd if=/dev/zero of=loadfile bs=1M count=5000触发):

  • 首先使用top命令查看当前io等待情况,如下可以看到当前io等待时间为84.7
Tasks:   total,    running,   sleeping,    stopped,    zombie
%Cpu(s): 0.7 us, 14.6 sy, 0.0 ni, 0.0 id, 84.7 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : total, free, used, buff/cache
KiB Swap: total, free, used. avail Mem
  • 使用iostat查看具体磁盘使用情况(当前系统只有一块磁盘),主要关注以下几个值

util:采集周期内用于IO操作的时间比率,该值过高直接说明IO占比过高,下面util已经升到了97.19%,IO已经很高了

await:平均每次IO请求等待时间(包括等待时间和处理时间,毫秒为单位),该值过高说明IO队列可能比较长,IO队列长度可以参考avgqu-sz(平均等待处理的IO请求队列长度)

svctm:平均每次IO请求的处理时间(毫秒为单位),正常情况下该值与await相差不大,差距越大,越说明IO过高。

IO有读写之分,如下例中明显写操作IO影响了性能,且设备为磁盘sda(iostat -x -k -d 1 2

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda 0.00 0.00 1.04 227.08 4.17 108850.00 954.34 124.40 1056.26 87.00 1060.71 4.26 97.19
    • 使用iotop -P查看当前IO占用率最高的进程,可以看到是一个PID为15162的进程,其IO达到了80.05%
Total DISK READ :       0.00 B/s | Total DISK WRITE :     403.22 M/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 411.90 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
be/ root 0.00 B/s 403.22 M/s 0.00 % 80.05 % dd if=/dev/zero...
...

使用lsof查看该进程打开的文件,可以看到/home/loadfile的大小达到了4564156416

# lsof -p
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
Output information may be incomplete.
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
dd root cwd DIR , /home
dd root rtd DIR , /
dd root txt REG , /usr/bin/dd
dd root mem REG , /usr/lib/locale/locale-archive
dd root mem REG , /usr/lib64/libc-2.17.so
dd root mem REG , /usr/lib64/ld-2.17.so
dd root 0r CHR , 0t0 /dev/zero
dd root 1w REG , 4564156416 /home/loadfile
dd root 2u CHR , 0t0 /dev/pts/

确定/home/loadfile文件的挂载路径,为根路径

# df /home/
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/centos-root % /

查看根路径挂载的磁盘(本例中为一块磁盘,可以忽略该步骤),为发生IO性能问题的磁盘sda,到此基本可以确认是因为进程15162引发了IO问题。注:可以使用如“time dd if=/dev/zero bs=1M count=2048 of=direct_2G”命令测试磁盘性能

# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda : 20G disk
├─sda1 : 1G part /boot
└─sda2 : 19G part
├─centos-root : 17G lvm /
└─centos-swap : 2G lvm [SWAP]

linux 大页

Linux采用了通用的分页模型,用以减少进程使用的页表以及增加对内存的索引。在Linux-2.6.10版本中, Linux采用了三级分页模型. 而从2.6.11开始普遍采用了四级分页模型,32位系统中取消了PUD和PMD,为二级分页模型。注:每个进程都有其自身的页面目录PGD

    1. 页全局目录(Page Global Directory)
    2. 页上级目录(Page Upper Directory)
    3. 页中间目录(Page Middle Directory)
    4. 页表(Page Table)

下面是一个线性地址包含的各字段以及各字段的用途

注:CR3中含有页目录表物理内存基地址,因此该寄存器也被称为页目录基地址寄存器PDBR(Page-Directory Base address Register),用于定位进程PGD

对于32位系统来说,如果采用4K的分页大小,每个PGD含1024个目录,每个目录含1024个PT,每个PT可寻址4K物理内存,总计4G。从上述可以看出,当进程需要访问实际物理内存时需要经过多级页才行,为了增加地址访问效率,linux使用了一种页缓存,TLB(translation lookaside buffer)。当需要访问物理地址时会首先从TLB中寻找,若找到则称为TLB hit,否则称为TLB miss。

这篇文章描述了使用系统默认4k分页下出现的性能问题,总结下来就是:64位系统下,一个进程访问的内存空间变大时,其PGD里面的页表项也会变大,如一个进程访问一个12G内存时,其页表需要24M,当300个进程同时需要访问这12G内存时,总的页表达到了7200MB,这么大的页表不仅占用大量内存空间,页增加了地址访问的负担(TLB miss也会大大增加)。解决办法是使用大页内存,通过增加单个分页大小,进而减少总体需要的分页的数目(同时也提升了TLB hit的几率)

可以看出,大页内存一般用于64位系统或32位系统启用了PAE(内存地址扩展)的情况。页表的使用情况可以参见/proc/meminfo中的PageTables字段

下面描述来自这里

典型地,内存管理器在 x86 系统上处理的内存页为 4 KB。实际的页大小是与体系结构相关的。对大部分用途来说,内存管理器以这样大小的页来管理内存是最有效的。不过,有一些应用程序要使用特别多的内存。大型数据库就是其中一个常见的例子。由于每个页都要由每个进程映射,必须创建页表条目来将虚拟地址映射到物理地址。如果您的一个进程要使用 4KB 的页来映射 1 GB 内存,这将用到 262,144 个页表条目来保持对那些页的追踪。如果每个页表条目消耗 8 个字节,那些每映射 1 GB 内存需要 2 MB 的开销。这本身就已经是非常可观的开销了,不过,如果有多个进程共享那些内存时,问题会变得更严重。在这种情况下,每个映射到同一块 1 GB 内存的进程将为页表条目付出自己 2 MB 的代价。如果有足够多的进程,内存在开销上的浪费可能会超过应用程序请求使用的内存数量。

解决这一问题的一个方法是使用更大的页。大部分新的处理器都支持至少一个小的和一个大的内存页大小。在 x86 上,大内存页的大小是 4 MB,或者,在物理地址扩展(PAE)打开的系统上是 2 MB。假定在前面的中使用页大小为 4 MB 的大内存页,同样 1 GB 内存只用 256 个页表条目就可以映射,而不需要 262,144 个。这样开销从 2 MB 变为 2,048 个字节。

大内存页的使用还可以通过减少 变换索引缓冲(translation lookaside buffer, TLB)的失败次数来提高性能。TLB 是一种页表的高速缓存,让那些在表中列出的页可以更快地进行虚拟地址到物理地址的转换。大内存页可以用更少的实际页来提供更多的内存,相当于较小的页大小,使用的大内存页越多,就有越多的内存可以通过 TLB 引用。

TIPS:

  • 衡量IO资源的时候,一般使用两个单位,一个是数据读写的带宽,另一个是数据读写的IOPS。带宽就是以时间为单位的读写数据量,比如,100Mbyte/s。而IOPS是以时间为单位的读写次数。
  • docker对io的的设置参数为--blkio-weight和--blkio-weight-device,一个是针对所有设备的,另一个是针对特定设备的,设置的都是相对比例,设置范围为0-1000
  • IO调度算法主要用于在机械硬盘场景下减少磁头寻址造成的性能浪费,磁头寻址时间一般以毫秒为单位。3~15ms

参考:

https://blog.csdn.net/gzh0222/article/details/8666657

https://www.ibm.com/developerworks/cn/linux/l-lo-io-scheduler-optimize-performance/index.html

https://zorro.gitbooks.io/poor-zorro-s-linux-book/content/linuxde-io-diao-du.html

http://bencane.com/2012/08/06/troubleshooting-high-io-wait-in-linux/

https://www.ibm.com/developerworks/cn/linux/l-memmod/index.html

https://www.ibm.com/developerworks/cn/linux/l-cn-hugetlb/

https://github.com/gatieme/LDD-LinuxDeviceDrivers/blob/master/study/kernel/02-memory/02-pagetable/01-develop/README.md

cgroup其他部分 IO + hugepage的更多相关文章

  1. Linux资源管理-IO优先级

    前一篇博客介绍了利用 cgroup 来控制进程的 CPU和内存使用情况, 这次补上使用 cgroup 来控制进程的IO优先级的方法. 前提条件 如果想控制进程的IO优先级, 需要内核的支持, 内核编译 ...

  2. Linux的IO调度

    Linux的IO调度 IO调度发生在Linux内核的IO调度层.这个层次是针对Linux的整体IO层次体系来说的.从read()或者write()系统调用的角度来说,Linux整体IO体系可以分为七层 ...

  3. 如何提高Linux下块设备IO的整体性能?

    编辑手记:本文主要讲解Linux IO调度层的三种模式:cfp.deadline和noop,并给出各自的优化和适用场景建议. 作者简介: 邹立巍 Linux系统技术专家.目前在腾讯SNG社交网络运营部 ...

  4. Linux内核配置选项

    http://blog.csdn.net/wdsfup/article/details/52302142 http://www.manew.com/blog-166674-12962.html Gen ...

  5. 乐视云计算基于OpenStack的IaaS实践

    本文作者岳龙广,现在就职于乐视云计算有限公司,负责IaaS部门的工作. 从开始工作就混在开源世界里,在虚拟化方面做过CloudStack/Ovirt开发,现在是做以OpenStack为基础的乐视云平台 ...

  6. 进程的proc文件系统信息

    一.实验代码 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include &l ...

  7. 架构师养成记--21.netty编码解码

    背景 作为网络传输框架,免不了哟啊传输对象,对象在传输之前就要序列化,这个序列化的过程就是编码过程.接收到编码后的数据就需要解码,还原传输的数据. 代码 工厂类 import io.netty.han ...

  8. 架构师养成记--20.netty的tcp拆包粘包问题

    问题描述 比如要发ABC DEFG HIJK 这一串数据,其中ABC是一个包,DEFG是一个包,HIJK是一个包.由于TCP是基于流发送的,所以有可能出现ABCD EFGH 这种情况,那么ABC和D就 ...

  9. Linux systemd资源控制初探

    Linux systemd资源控制初探 本文记录一次cgroup子目录丢失问题,并简单探索了Linux systemd的资源控制机制. 问题现象 我们希望通过systemd拉起服务并通过cgroup限 ...

随机推荐

  1. springboot自带定时任务和集成quartz

    1,springboot自带的定时任务  默认是单线程 有这个依赖就可以 <dependency> <groupId>org.springframework.boot</ ...

  2. node.js中使用yargs来处理命令行参数

    yargs库能够方便的处理命令行参数. 一.安装 yargs npm install yargs --save 二.读取命令行参数 const yargs = require('yargs'); le ...

  3. Kettle (5) - 获取 Web 数据

    使用 Kettle 获取网页数据.当然,这里的网页数据主要指结构化数据,可能是 xml 格式.json 格式 或者 csv 文件等.以 http://services.odata.org/V3/Nor ...

  4. 获取fastdfs所有文件

    工作中,mysql中存储的图片链接信息和FastDFS实际存储的图片数量不一致,此时应该与mysql中有存储记录的图片保持一致,我们要在FastDFS服务器中删除哪些无用的图片.于是乎自己写了一个脚本 ...

  5. AUTEL MaxiSys MS908S Pro MS908SP Diagnostic Platform

    AUTEL MaxiSys MS908S Pro Description : One of the MaxiSys series devices, the MS908S Pro Diagnostic ...

  6. SQL SERVER中LIKE在Char和nChar输出结果不一致解惑

    一同事在写脚本时,遇到一个关于LIKE里面使用不同的变量类型导致查询结果不一致的问题,因为这个问题被不同的人问过好几次,索性总结一下,免得每次都要解释一遍,直接丢一篇博客岂不是更方便!其实看似有点让人 ...

  7. MFC设置单文档保存格式以及标题

    在使用MFC编写单文档程序时,有时候需要将编辑的内容序列化为文件,使该文件可以直接以自己的程序打开,这时候需要在保存时将文件后缀改为我们想要的格式. 步骤 打开String Table,找到IDR_M ...

  8. 深入浅出WPF文摘

    第一部分 深入浅出XMAL 第一章 XMAL概览 第二章 从零起步认识XMAL 第三章 系统学习XMAL语法 第四章 X名称空间详解 第五章 控件与布局 GUI:图形化用户界面 逻辑树: 可视树: : ...

  9. html 2

    一.列表 信息资源的一种展示形式 二.列表的分类 1.有序列表 <ol> <li>列表项1</li> <li>列表项2</li> </ ...

  10. cf 700e(sam好题,线段树维护right)

    代码参考:http://blog.csdn.net/qq_33229466/article/details/79140428 #include<iostream> #include< ...