Linux性能优化之CPU、内存、IO优化

系统调优 专栏收录该内容
16 篇文章 1 订阅

 Linux 的性能进行监测,以下是 VPSee 常用的工具:
工具    简单介绍
top    查看进程活动状态以及一些系统状况
vmstat    查看系统状态、硬件和系统信息等
iostat    查看CPU 负载,硬盘状况
sar    综合工具,查看系统状况
mpstat    查看多处理器状况
netstat    查看网络状况
iptraf    实时网络状况监测
tcpdump    抓取网络数据包,详细分析
tcptrace    数据包分析工具
netperf    网络带宽工具

 

dstat    综合工具,综合了 vmstat, iostat, ifstat, netstat 等多个信息

 

 

 

Linux性能优化之CPU优化(一)

 

 

 

前言

何为性能优化?个人认为,性能优化是为了提高应用程序或系统能力为目的。那么如何才能实现对应用程序的性能调优呢?这里很设计到很多的内容,包括Linux内核、CPU架构以及Linux内核对资源的分配以及管理,了解进程的创建过程等。这方面由于篇幅较多,所以我的文章就不过多介绍。接下来的几篇文章中,都是讲解如何发现应用程序故障根源为目标讲解,这也是每一个系统工程师应该具备的能力。废话不多说,我直接进入主题。

常用术语

  延时:延时是描述操作之后用来等待返回结果的时间。在某些情况下,它可以指的是整个操作时间,等同于响应时间。

  IOPS:每秒发生的输入/输出操作的次数,是数据传输的一个度量方法。对于磁盘的读写,IOPS指的是每秒读写的次数。

  响应时间:一般操作完成的时间。包括用于等待和服务的时间,也包括用来返回结果的时间。

  使用率:对于服务所请求的资源,使用率描述在所给定时间区间内资源的繁忙程度。对于春初资源来说,使用率指的就是所消耗的存储容量。

  饱和度:指的就是某一资源无法满足服务的排队工作量。

  吞吐量:评价工作秩序的速率,尤其是在数据传输方面,这个属于用于数据传输速度(字节/秒和比特/秒)。在某些情况下,吞吐量指的是操作的速度。

Linux内核功能

  CPU调度级别:各种先进的CPU调度算法,非一直存储访问架构(NUMA);

  I/O调度界别:I/O调度算法,包括deadline/anticipatory和完全公平队列(CFQ);

  TCP网络阻塞:TCP拥堵算法,允许按需选择;

常见问题

进程、线程和任务之间的区别是什么?

  进程通常定义为程序的执行。用以执行用户级别程序的环境。它包括内存地址空间、文件描述符、线程栈和寄存器。
  线程是某一进程中单独运行的程序。也就是说线程在进程之中。
  任务是程序完成的某一活动,可以使一个进程,也可以是一个线程。

参考连接:http://blog.chinaunix.net/uid-25100840-id-271078.html

什么是上下文切换?

  执行一段程序代码,实现一个功能的过程介绍,当得到CPU的时候,相关的资源必须也已经就位,就是显卡、内存、GPS等,然后CPU开始执行。这里除了CPU以外所有的就构成了这个程序的执行环境,也就是我们所定义的程序上下文。当这个程序执行完或者分配给他的CPU执行时间用完了,那它就要被切换出去,等待下一次CPU的临幸。在被切换出去的最后一步工作就是保存程序上下文,因为这个是下次他被CPU临幸的运行环境,必须保存。

I/O密集型和CPU密集型工作负载之间的区别?

  I/O密集型指的是系统的CPU耗能相对硬盘/内存的耗能能要好很多,此时,系统运作,大部分的状况是 CPU 在等 I/O(硬盘/内存)的读/写,此时CPU负载不高。CPU密集型指的是系统的硬盘/内存耗能相对CPU的耗能要好很多,此时,系统运作,大部分的状况是 CPU负载 100%,CPU 要读/写 I/O (硬盘/内存),I/O在很短的时间就可以完成,而CPU还有许多运算要处理,CPU负载很高。一般而言CPU占用率相当高,大部份时间用来做计算、逻辑判断等CPU动作的程序。

应用程序性能技术

1.选择I/O尺寸
  执行I/O的开销包括初始化缓冲区、系统调用、上下文切换、分配内核元数据、检查进程权限和限制、映射地址到设备、执行内核和驱动代码来执行I/O,以及在最后释放元数据和缓冲区。增加I/O尺寸是应用程序提高吞吐量的常用策略。
2.缓存
  操作系统用缓存提高文件系统的读性能和内存的分配性能,应用程序使用缓存也处于类似的原因。将经常执行的操作结果保存在本地缓存中以备后用,而非总是执行开销较高的操作。
3.缓冲区
  为了提高写操作性能,数据在送入下一层级之前会合并并放在缓冲区中。这样会增加写延时,因为第一次写入缓冲区后,在发送之前,还要等待后续的写入。
4. 并发和并行
  并行:装在和开始执行多个可运行程序的能力(比如,同时接电话和吃饭)。为了利用多核处理器系统的优势,应用程序需要在同一时间运行在多颗CPU上,这种方式称为并行。应用程序通过多进程或多线程实现。
  并发:有处理多个任务的能力,不一定要同时。比如,接完电话在去吃饭,存在资源抢占;
  同步原语:同步原语监管内存的访问,当不允许访问时,就会引起等待时间(延时)。常见三种类型:
  mutex锁:只有锁持有者才能操作,其他线程会阻塞并等待CPU;
  自旋锁:自旋锁允许锁持有者操作,其他的需要自旋锁的线程会在CPU上循环自选,检查锁是否被释放。虽然这样可以提供低延时的访问,被阻塞的线程不会离开CPU,时刻准备着运行知道锁可用,但是线程自旋、等待也是对CPU资源的浪费。
  读写锁:读/写锁通过允许多个读者或者只允许一个写者而没有读者,来保证数据的完整性。
  自适应自旋锁:低延迟的访问而不浪费CPU资源,是mutex锁和自旋锁的混合。
5.绑定CPU

关于CPU性能分析

uptime:
  系统负载,通过汇总正在运行的线程数和正在排队等待运行的线程数计算得出。分别反映1/5/15分钟以内的负载。现在的平均负载不仅用来表示CPU余量或者饱和度,也不能单从这个值推断出CPU或者磁盘负载。

vmstat:
  虚拟内存统计信息命令。最后几列打印系统全局范围内的CPU使用状态,在第一列显示可运行进程数。如下所示:

1

2

3

4

[root@zbredis-30104 ~]# vmstat

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----

r  b   swpd   free   buff   cache   si   so    bi    bo   in   cs us sy id  wa  st

0  0   0    14834208 158384 936512  0     0     0     0    1   3   0  0 100  0  0

提示:

  r: 运行队列长度和正在运行的线程数;

  b: 表示阻塞的进程数;

  swpd: 虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器;

  si: 每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。我的机器内存充裕,一切正常。

  so: 每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上;

  bi: 块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0,但是我曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速度差不多140M每秒;

  bo: 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整;

  in: 每秒CPU的中断次数,包括时间中断;

  cs:  每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。

  st: cpu在虚拟化环境上在其他租户上的开销;

mpstat:
  多处理器统计信息工具,能够报告每个CPU的统计信息。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

[root@zbredis-30104 ~]# mpstat -P ALL 1

Linux 2.6.32-573.el6.x86_64 (zbredis-30104)     09/14/2017  _x86_64_    (12 CPU)

 

03:14:03 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle

03:14:04 PM  all    0.00    0.00    0.08    0.00    0.00    0.00    0.00    0.00   99.92

03:14:04 PM    0    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM    1    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM    2    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM    3    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM    4    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM    5    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM    6    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM    7    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM    8    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM    9    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM   10    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

03:14:04 PM   11    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

提示:

  irq: 硬件中断CPU用量;

  sofr: 软件中断CPU用量;
  steal: 耗费在服务其他租户的时间;
  guest: 花在访客虚拟机的时间;

  重要关注列有%user/%sys/%idle。显示了每个CPU的用量以及用户态和内核态的时间比例。可以根据这些值查看那些跑到100%使用率(%user + %sys)的CPU,而其他CPU并未跑满可能是由单线程应用程序的负载或者设备中断映射造成。

sar:

  系统活动报告器。用来观察当前的活动,以及配置用以归档和报告历史统计信息。基本上所有资源使用的信息,它都能够查看到。具体的参数说明如下所示:

  -A: 所有报告的总和,类似"-bBdqrRSuvwWy -I SUM -I XALL -n ALL -u ALL -P ALL"参数一起使用;
  -b: 显示I/O和传输速率的统计信息;
  -B:显示分页状态;
  -d:硬盘使用报告;
  -r:内存和交换空间的使用统计;
  -g:串口I/O的情况;
  -b:缓冲区使用情况;
  -a:文件读写情况;
  -c:系统调用情况;
  -n: 统计网络信息;
  -q:报告队列长度和系统平均负载;
  -R:进程的活动情况;
  -y:终端设备活动情况;
  -w:系统交换活动;
  -x { pid | SELF | ALL }:报告指定进程ID的统计信息,SELF关键字是sar进程本身的统计,ALL关键字是所有系统进程的统计;

常用参数组合:

  查看CPU:

  整体CPU统计— sar -u 3 2,表示采样时间为3秒,采样次数为2次;
  各个CPU统计— sar -P ALL 1 1,表示采样时间为1秒,次数为1次;

    1. 若 %iowait 的值过高,表示硬盘存在I/O瓶颈;
    2. 若 %idle 的值高但系统响应慢时,有可能是 CPU 等待分配内存,此时应加大内存容量;
    3. 若 %idle 的值持续低于1,则系统的 CPU 处理能力相对较低,表明系统中最需要解决的资源是 CPU;

  查看内存:

  查看内存使用情况 - sar -r 1 2

    kbcommit:保证当前系统所需要的内存,即为了确保不溢出而需要的内存(RAM+swap);
    %commit:这个值是kbcommit与内存总量(包括swap)的一个百分比;

  pidstat:主要用于监控全部或指定进程占用系统资源的情况,如CPU,内存、设备IO、任务切换、线程等。

  cpu使用情况统计
    执行 "pidstat -u" 与单独执行 "pidstat"
  内存使用情况统计
    pidstat -r -p PID 1

    minflt/s: 每秒次缺页错误次数(minor page faults),次缺页错误次数意即虚拟内存地址映射成物理内存地址产生的page fault次数;
    majflt/s: 每秒主缺页错误次数(major page faults),当虚拟内存地址映射成物理内存地址时,相应的page在swap中,这样的page fault为major page fault,一般在内存使用紧张时产生;
  IO情况统计
    pidstat -d 1 2

关于CPU方面的优化

  1.编译器优化
  2.调度优先级和调度类(设置nice值)
    例如,nice -n 19 command
    renice 更改已经运行进程的优先级;
    chrt 命令显示并直接修改优先级和调度策略;
  3.进程绑定(一个进程可以绑定在一个或者多个CPU上)
    例如,taskset -pc 0-3 10790

  4.独占CPU
  5.BIOS调优
    启用睿频

 

 

 

 

Linux性能优化之内存优化(二)

 

 

 

前言

  不知道大家看完前面一章关于CPU优化,是否受到相应的启发呢?如果遇到任何问题,可以留言和一起探讨这方面的问题。接下来我们介绍一些关于内存方面的知识。内存管理软件包括虚拟内存系统、地址转换、交换、换页和分配。与性能密切相关的内容包括:内存释放、空闲链表、页扫描、交换、进程地址空间和内存分配器。在Linux中,空闲链表通常由分配器消耗,如内核的slab分配器和SLUB,以及用户级分配器(glibc,linux系统)libmalloc、libumem和mtmalloc。

  • slab: 内核slab分配器管理特定大小的对象缓存,使他们能够被快速的回收利用,并且避免页分配的开销。适用于处理固定大小结构的内核内存分配。
  • slub: 基于slab分配器。它主要是解决slab分配器带来的问题,其中包括移除对象队列,以及每个CPU缓存,把NUMA优化留给页分配器。
  • glibc: 结合多种非配器策略的高效分配器,它基于分配请求的长度进行分配。较小的分配来自内存集合,包括用伙伴关系算法合并长度相近的单位。较大的分配用树高效地搜索空间。对于非常大的分配,会转到mmap()。

  回收大多是从内核的slab分配器缓存释放内存。这些缓存包含slab大小的未使用内存块,以供充裕。内核页面换出守护进程管理利用换页释放内存。当主存中可用的空闲链表低于阈值时,页面换出守护进程会开始页扫描。页面换出守护进程被称作kswapd(),它扫描非活动和活动内存的LRU页列表以释放页面。它的激活基于空闲内存核两个提供滞后的阈值。一旦空闲内存达到最低阈值,kswapd运行于同步模式,按需求释放内存页。该最低阈值是可调的(vm.min_free_kbytes),并且其他阈值基于它按比例放大。

相关概念

  • 主存:物理内存,描述了计算机的告诉数据存储区域,通常是动态随机访问内存;
  • 虚拟内存: 抽象的主从概念,它几乎是无限的和非竞争性的;
  • 常驻内存:当前处于主存中的内存;
  • 匿名内存:无文件系统位置或者路径名的内存。它包括进程地址空间的工作数据,称作堆;
  • 地址空间:内存上下文。每个进程和内核都有对应的虚拟地址空间;
  • 页:操作系统和CPU使用的内存单位。它一直以来是4KB和8KB。现代的处理器允许多种页大小以支持更大的页面尺寸,以及更大的透明大页;
  • 缺页:无效的内存访问;
  • 换页:在主存与存储设备间交换页;
  • 交换:指页面从主从转移到交换设备(迁移交换页);
  • 交换(空间):存放换页的匿名数据和交换进程的磁盘空间;

  进程地址空间是一段范围的虚拟页,由硬件和软件同事管理,按需映射到物理页。这些地址被划分为段以存放线程栈、进程可执行、库和堆。应用程序可执行段包括分离的文本和数据段。库也由分离的可执行文本和数据段组成。分别如下:

  • 可执行文本:包括可执行的进程CPU指令。由文件系统中的二进制应用程序文本映射而来。它是只读的并带有执行的权限。
  • 可执行数据:包括已初始化的变量,由二进制应用程序的数据段映射而来。有读写权限,因此这些变量在应用程序的运行过程中可以被修改。
  • 堆:应用程序的临时工作内存并且是匿名内存。它按需增长并且用mollac()分配。
  • 栈:运行中的线程栈,映射为读写。

  对于内存而言,经常关注的信息如下:

  • 页扫描:寻找连续的页扫描(超过10秒),它是内存压力的预兆。可以使用sar -B并查看pgscan列。
  • 换页:换页是系统内存低的进一步征兆。可以使用vmstat 并查看si(换入) 和 so(换出)列。
  • 可用内存:查看和关注buffer和cache值;
  • OOM终结者:在系统日志/var/log/messages或者dmesg中查看,直接搜索"Out of memory";
  • top/prstat:查看那些进程和用户是常驻物理内存和虚拟内存的最大使用者;
  • stap/perf:内存分配的栈跟踪,确认内存使用的原因;

  如何快速定位内存故障?
  1. 首先应该检查饱和度(作为释放内存压力的衡量,页扫描、换页、交换和Linux OOM终结者牺牲进度的使用程度),因为持续饱和状态是内存问题的征兆。这些指标可以通过vmstat、sar、dmesg等操作系统工具轻易获得。对于配置了独立磁盘交换设备的系统,任何交换设备活动都是内存压力的征兆。

  2. 使用率(使用内存和可用内存,物理内存和虚拟内存都应该关注)通常较难读取和解读。比如一个系统可能会报告只有几十兆内存可用,但事实上它有10GB的文件系统缓存在,需要时立刻被应用程序回收利用。虚拟内存使用,这应该也是我们关注的一个点。

  3. 内存错误(Out of memory)一般都是由应用程序报告。

关于内存性能排查命令

vmstat

1

2

3

4

[root@zbredis-30104 ~]# vmstat

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----

r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st

0  0    0 14834208 158384 936512    0    0     0     0    1    3  0  0 100  0  0

提示:

  swpd:交换处的内存量;
  free:空闲的可用内存;
  buff: 用户缓冲缓存的内存;
  cache: 用于页缓存的内存;
  si: 换入的内存(换页);
  so:换出的内存(换页);

如果si 和 so列一直非0,那么系统正存在内存压力并换页到交换设备或文件。经常使用参数为"vmstat 1 -Sm"和"vmstat -a 1";

sar

  -B: 换页统计信息;

  -H: 大页面统计信息
  -r: 内存使用率
  -R:内存统计信息
  -S:交换空间统计信息
  -W:交换统计信息

slabtop

  通过slab分配器实时输出内核slab缓存使用情况;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

[root@localhost ~]# slabtop -sc

 

Active / Total Objects (% used)    : 297064 / 300262 (98.9%)

Active / Total Slabs (% used)      : 6638 / 6638 (100.0%)

Active / Total Caches (% used)     : 66 / 96 (68.8%)

Active / Total Size (% used)       : 80612.41K / 81749.09K (98.6%)

Minimum / Average / Maximum Object : 0.01K / 0.27K / 8.00K

 

OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                  

7648   7528  98%    2.00K    478     16     15296K kmalloc-2048

65142  65142 100%    0.19K   1551    42     12408K dentry

17985  17985 100%    0.58K    327    55     10464K inode_cache

7110   7110 100%    1.06K    237     30  7584K xfs_inode

10880  10160  93%    0.50K    170    64  5440K kmalloc-512

30564  30564 100%    0.11K    849    36  3396K sysfs_dir_cache

输出包括顶部的汇总和slab列表。其中包括对象数量(OBJS)、多少是活动的(ACTIVE)、使用百分比(USE)、对象大小(OBJ SIZE,字节)和缓存大小(CACHE SIZE,字节)。

ps

  可以列出包括内存使用统计信息在内的所有进程细节;

  %MEM: 主存使用(物理内存、RSS)占总内存的百分比;
  RSS:常驻集合大小;
  VSZ: 虚拟内存大小;

提示:RSS显示主存使用,它也包括如系统库在内的映射共享段,可能会被几十个进程共享。如果你把RSS列求和,会发现她超过系统内存总和,这是由于重复计算了这部分共享内存。

pmap

1

2

3

4

5

6

7

8

9

10

11

12

13

14

[root@localhost ~]# pmap -x 1096

1096:   /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock

Address           Kbytes     RSS   Dirty Mode  Mapping

0000000000400000   11960    3468       0 r-x-- mysqld

00000000011ae000     668     240     172 r---- mysqld

0000000001255000    1028     364     208 rw--- mysqld

0000000001356000     340     312     312 rw---   [ anon ]

0000000001887000    7508    7344    7344 rw---   [ anon ]

...省略部分...

00007ffc659e9000     132      72      72 rw---   [ stack ]

00007ffc65ba1000       8       4       0 r-x--   [ anon ]

ffffffffff600000       4       0       0 r-x--   [ anon ]

---------------- ------- ------- -------

total kB          961172  121756  116468

内存优化

首先关于内核优化的相关参数

vm.dirty_background_bytes:默认值为0, 触发pdflush后台回写的脏存储器量;

vm.dirty_background_ratio:默认值10, 触发pdflush后台回写脏系统存储器百分比;
vm.dirty_bytes:默认值为0,触发一个写入进程开始回写的脏存储器量;
vm.dirty_ratio:默认值为20,触发一个写入进程开始回写的脏系统存储器比例;
vm.dirty_expire_centisecs:默认值为3000,使用pdflush的脏存储器最小时间;
vm.dirty_writeback_centisecs:默认值为500,pdflush活跃时间间隔(0为停用);
vm.min_free_kbytes:默认值为 dynamic,设置期望的空闲存储器量(一些内核自动分配器能消耗它);
vm.overconmmit_memory:默认值为0,0表示利用探索法允许合理的国度分配;1表示一直国度分配;3表示禁止国度分配;
vm.swappiness:默认值为60,相对于页面高速缓存回收更倾向用交换释放存储器的程度;
vm.vfs_cache_pressure:默认值为100,表示回收高速缓存的目录和inode对象的程度。较低的值会保留更多;0意味着从不回收,容器导致存储器耗尽的情况;

提示:

vm.dirty_background_bytes和vm.dirty_background_ratio是互斥的,dirty_bytes 和 dirty_ratio 也是如此,仅能设置一个。vm.swappiness参数对性能会产生显著的影响,建议设置为0;因为应用程序内存能尽可能就地驻留。

       最后说明,在现在内核发展过程之中,linux内存页面已经支持大页面和超大页面以及透明大页面等,可以根据自身环境进行适当的调整。红帽企业版 Linux 6 采用第二种方法,即使用超大页面。简单说,超大页面是 2MB 和 1GB 大小的内存块。2MB 使用的页表可管理多 GB 内存,而 1GB 页是 TB 内存的最佳选择。

       超大页面必须在引导时分配。它们也很难手动管理,且经常需要更改代码以便可以有效使用。因此红帽企业版 Linux 也部署了透明超大页面 (THP)。THP 是一个提取层,可自动创建、管理和使用超大页面的大多数方面。

THP 系统管理员和开发者减少了很多使用超大页面的复杂性。因为 THP 的目的是改进性能,所以其开发者(社区和红帽开发者)已在各种系统、配置、程序和负载中测试并优化了 THP。这样可让 THP 的默认设置改进大多数系统配置性能。

  注:THP 目前只能映射异步内存区域,比如堆和栈空间。关于THP相关使用及问题可自行查阅资料。

overcommit_memory参数说明: 设置内存分配策略(可选,根据服务器的实际情况进行设置) /proc/sys/vm/overcommit_memory 可选值:0、1、2。 0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。

1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。

2, 表示内核允许分配超过所有物理内存和交换空间总和的内存

 

 

Linux性能优化之磁盘优化(三)

 

前言

 

关于本章内容,设计的东西比较多。这里会有关于文件系统、磁盘、CPU等方面的知识,以及涉及到关于这方面的性能排查等。

术语

文件系统通过缓存和缓冲以及异步I/O等手段来缓和磁盘的延时对应用程序的影响。为了更详细的了解文件系统,以下就简单介绍一些相关术语:

  • 文件系统:一种把数据组织成文件和目录的存储方式,提供了基于文件的存取接口,并通过文件权限控制访问。另外,一些表示设备、套接字和管道的特殊文件类型,以及包含文件访问时间戳的元数据。
  • 文件系统缓存:主存(通常是DRAM) 的一块区域,用来缓存文件系统的内容,可能包含各种数据和元数据。
  • 操作:文件系统的操作是对文件系统的请求,包括读、写、打开、关闭、创建以及其他操作。
  • I/O:输入/输出。文件系统I/O有多种定义,这里仅指直接读写(执行I/O)的操作,包括读、写、状态统计、创建。I/O不包括打开文件和关闭文件。
  • 逻辑I/O:由应用程序发给文件系统的I/O。
  • 物理I/O:由文件系统直接发给磁盘的I/O。
  • 吞吐量:当前应用程序和文件系统之间的数据传输率,单位是B/S。
  • inode:一个索引节点时一种含有文件系统对象元数据的数据结构,其中有访问权限、时间戳以及数据指针。
  • VFS:虚拟文件系统,一个为了抽象与支持不同文件系统类型的内核接口。

磁盘相关术语:

  • 存储设备的模拟。在系统看来,这是一块物理磁盘,但是,它可能由多块磁盘组成。
  • 传输总线:用来通信的物理总线,包括数据传输以及其他磁盘命令。
  • 扇区:磁盘上的一个存储块,通常是512B的大小。
  • I/O:对于磁盘,严格地说仅仅指读、写,而不包括其他磁盘命令。I/O至少由方向(读或写)、磁盘地址(位置)和大小(字节数)组成。
  • 磁盘命令:除了读写之外,磁盘还会被指派执行其他非数据传输的命令(例如缓存写回)。
  • 带宽:存储传输或者控制器能够达到的最大数据传输速率。
  • I/O延时:一个I/O操作的执行时间,这个词在操作系统领域广泛使用,早已超出了设备层。

相关概念

  文件系统延时
       文件系统延时是文件系统性能一项主要的指标,指的是一个文件系统逻辑请求从开始到结束的时间。它包括消耗在文件系统、内核磁盘I/O子系统以及等待磁盘设备——物理I/O的时间。应用程序的线程通常在请求时阻塞,等地文件系统请求的结束。这种情况下,文件系统的延时与应用程序的性能直接和成正比关系。在某些情况下,应用程序并不受文件系统的直接影响,例如非阻塞I/O或者I/O由一个异步线程发起。

  缓存

       文件系统启动之后会使用主存(RAM)当缓存以提供性能。缓存大小随时间增长而操作系统的空余内存不断减小,当应用程序需要更多内存时,内核应该迅速从文件系统缓存中释放一些内存空间。文件系统用缓存(caching)提高读性能,而用缓冲(buffering)提高写性能。文件系统和块设备子系统一般使用多种类型的缓存。

  随机I/O与顺序I/O
        一连串的文件系统逻辑I/O,按照每个I/O的文件偏移量,可以分为随机I/O与顺序I/O。顺序I/O里每个I/O都开始于上一个I/O结束的地址。随机I/O则找不出I/O之间的关系,偏移量随机变化。随机的文件系统负载也包括存取随机的文件。由于存储设备的某些性能特征的缘故,文件系统一直以来在磁盘上顺序和连续的存放文件数据,以努力减小随机I/O的数目。当文件系统未能达到这个目标时,文件的摆放变得杂乱无章,顺序的逻辑I/O被分解成随机的物理I/O,这种情况被称为碎片化。

提示:关于文件系统更多内容,还请自行查阅相关理论。比如你还需要了解文件系统的预读、预取、写回缓存、同步写、裸I/O、直接I/O、内存映射文件、元数据等相关知识。

性能分析

具备背景知识是分析性能问题时需要了解的。比如硬件 cache;再比如操作系统内核。应用程序的行为细节往往是和这些东西互相牵扯的,这些底层的东西会以意想不到的方式影响应用程序的性能,比如某些程序无法充分利用 cache,从而导致性能下降。比如不必要地调用过多的系统调用,造成频繁的内核 / 用户切换等。如果想深入了解Linux系统,建议购买相关书籍进行系统的学习。下面我们介绍如何分析磁盘性能工具(其实准确来说,不只是磁盘):

iostat

汇总了单个磁盘的统计信息,为磁盘负载、使用率和饱和度提供了指标。默认显示一行系统总结信息,包括内核版本、主机名、日志、架构和CPU数量等,每个磁盘设备都占一行。

1

2

3

4

5

6

7

8

9

10

11

[root@localhost ~]# iostat

Linux 3.10.0-514.el7.x86_64 (localhost.localdomain)     2017年09月18日     _x86_64_    (1 CPU)

 

avg-cpu:  %user   %nice %system %iowait  %steal   %idle

           0.74    0.00    1.24    1.35    0.00   96.67

 

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn

sda              14.43       456.85        60.82     218580      29098

scd0              0.02         0.09         0.00         44          0

dm-0             13.65       404.58        56.50     193571      27030

dm-1              0.27         2.23         0.00       1068          0

参数说明

  • tps: 每秒事物数(IOPS)。
  • kB_read/s、kB_wrtn/s: 每秒读取KB数和每秒写入KB数。
  • kB_read、kB_wrtn: 总共读取和写入的KB数。

如下想输出更详细的内容,可以试试下面这个命令组合:

1

2

3

4

5

6

7

8

[root@localhost ~]# iostat -xkdz 1

Linux 3.10.0-514.el7.x86_64 (localhost.localdomain)     2017年09月18日     _x86_64_    (1 CPU)

 

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.01     2.43   13.81    2.32   510.51    67.96    71.74     0.22   13.94    8.72   44.95   2.37   3.82

scd0              0.00     0.00    0.03    0.00     0.10     0.00     8.00     0.00    0.27    0.27    0.00   0.27   0.00

dm-0              0.00     0.00   10.52    4.73   452.10    63.13    67.56     0.44   28.56   10.41   68.93   2.47   3.76

dm-1              0.00     0.00    0.30    0.00     2.49     0.00    16.69     0.00    1.50    1.50    0.00   1.38   0.04

参数说明

  • rrqm/s:每秒合并放入驱动请求队列的读请求数(当系统调用需要读取数据的时候,VFS将请求发到各个FS,如果FS发现不同的读取请求读取的是相同Block的数据,FS会将这个请求合并Merge)。
  • wrqm/s:每秒合并放入驱动请求队列的写请求数。
  • rsec/s:每秒发给磁盘设备的读请求数。
  • wsec/:每秒发给磁盘设备的写请求数。
  • rKB/s:每秒从磁盘设备读取的KB数。
  • wKB/s:每秒向磁盘设备写入的KB数。
  • avgrq-sz 平均每次请求大小,单位为扇区(512B)。
  • avgqu-sz 在驱动请求队列和在设备中活跃的平均请求数。
  • await: 平均I/O响应时间,包括在驱动请求队列里等待和设备的I/O响应时间(ms)。一般地系统I/O响应时间应该低于5ms,如果大于10ms就比较大了。这个时间包括了队列时间和服务时间,也就是说,一般情况下,await大于svctm,它们的差值越小,则说明队列时间越短,反之差值越大,队列时间越长,说明系统出了问题。
  • svctm:磁盘设备的I/O平均响应时间(ms)。如果svctm的值与await很接近,表示几乎没有I/O等待,磁盘性能很好,如果await的值远高于svctm的值,则表示I/O队列等待太长系统上运行的应用程序将变慢。
  • %util: 设备忙处理I/O请求的百分比(使用率)。在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度。一般地,如果该参数是100%表示设备已经接近满负荷运行了(当然如果是多磁盘,即使%util是100%,因为磁盘的并发能力,所以磁盘使用未必就到了瓶颈)。

      既然avgrq-sz是合并之后的数字,小尺寸(16个扇区或者更小)可以视为无法合并的实际I/O负载的迹象。大尺寸有可能是大I/O,或者是合并的连续负载。输出性能里最重要的指标是await。如果应用程序和文件系统使用了降低写延时的方法,w_await可能不那么重要,而更应该关注r_await。
      对于资源使用和容量规划,%util仍然很重要,不过记住这只是繁忙度的一个度量(非空闲时间),对于后面有多块磁盘支持的虚拟设备意义不大。可以通过施加负载更好地了解这些设备:IOPS(r/s + w/s)以及吞吐量(rkB/s + wkB/s)。

iotop

包含磁盘I/O的top工具。

批量模式(-b)可以提供滚动输出。下面的演示仅仅显示I/O进程(-o),每5秒输出一次(-d5):

1

[root@localhost ~]# iotop -bod5

1

2

3

4

5

6

7

8

Total DISK READ :       0.00 B/s | Total DISK WRITE :       8.76 K/s

Actual DISK READ:       0.00 B/s | Actual DISK WRITE:      24.49 K/s

  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN      IO    COMMAND

21203 be/3 root        0.00 B/s  815.58 B/s  0.00 %  0.01 % [jbd2/dm-2-8]

22069 be/3 root        0.00 B/s    0.00 B/s  0.00 %  0.01 % [jbd2/dm-1-8]

 1531 be/0 root        0.00 B/s    6.37 K/s  0.00 %  0.01 % [loop0]

 3142 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.01 % [kworker/7:0]

21246 be/4 root        0.00 B/s 1631.15 B/s  0.00 %  0.00 % java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start

提示:

        输出显示java进程正在以大约1631.15 B/s的速率施加磁盘写负载。其他有用的选项有-a,可以输出累计I/O而不是一段时间内的平均值,选项-o,只打印那些正在执行的磁盘I/O的进程。

  当然显示磁盘的命令还有例如sar、iosnoop、perf、blktrace等命令,这里只列举常用命令即可。

性能调优

文件系统优化

关于文件系统优化,并没有太多的内容需要说明。就目前的情况,Redhat Enterprise 7系列默认更换为性能更好的XFS,这也是由于XFS在性能表现确实很好的原因。在我们使用的过程中,建议对XFS做一些简单的优化即可,比如执行格式化时指定额外的一些参数,挂载该分区时指定一些额外的挂载参数,这些都能够提高文件系统的相关性能。

格式化时的参数:

1

mkfs.xfs -d agcount=256 -l size=128m,lazy-count=1,version=2 /dev/diska1

mount时的参数:

1

defaults,noatime,nodiratime,nobarrier,discard,allocsize=256m,logbufs=8,attr2,logbsize=256k

磁盘相关优化

  • 操作系统可调参数

  包括ionice、资源控制和内核可调参数。

  ionice

  Linux中的ionice命令可以设置一个进程I/O调度级别和优先级。调度级别为整数,0表示无,不指定级别,内核会挑选一个默认值,优先级根据进程nice值选定;1表示实时,对磁盘的最高级别访问,如果误用会导致其他进程饿死;2表示尽力,默认调度级别,包括优先级 0~7,0为最高级;3表示空闲,在一段磁盘空闲的期限过后才允许进行I/O。如下:

1

ionice -c 3 -p 65552

    cgroup

  通过cgroup为进程或进程组提供存储设备资源控制机制。一般很少用到,不用考虑。

    可调参数

  /sys/block/sda/queue/scheduler:选择I/O调度器策略,是空操作、最后期限、an还是cfq;

  • 磁盘设备可调参数

  Linux上的hdparm(磁盘测试工具)工具可以设置多种磁盘设备的可调参数。

  • 磁盘控制器可调参数

 

由于各种的I/O负载情形各异,Linux系统中文件系统的缺省配置一般来说都比较中庸,强调普遍适用性。然而在特定应用下,这种配置往往在I/O性能方面不能达到最优。因此,如果应用对I/O性能要求较高,除了采用性能更高的硬件(如磁盘、HBA卡、CPU、MEM等)外,我们还可以通过对文件系统进行性能调优,来获得更高的I/O性能提升。总的来说,主要可以从三个方面来做工作:

1、Disk相关参数调优

2、文件系统本身参数调优

3、文件系统挂载(mount)参数调优

 

当然,负载情况不同,需要结合理论分析与充分的测试和实验来得到合理的参数。下面以SAS(Serial attached SCSI)磁盘上的EXT3文件系统为例,给出Linux文件系统性能优化的一般方法。请根据自身情况作适合调整,不要生搬硬套。

 

1、Disk相关参数

1.1 Cache mode:启用WCE=1(Write Cache Enable), RCD=0(Read Cache Disable)模式

sdparm -s WCE=1, RCD=0 -S /dev/sdb

 

1.2 Linux I/O scheduler算法

经过实验,在重负载情形下,deadline调度方式对squidI/O负载具有更好的性能表现。其他三种为noop(fifo), as, cfq,noop多用于SAN/RAID存储系统,as多用于大文件顺序读写,

 

cfq适于桌面应用。

echo deadline > /sys/block/sdb/queue/scheduler

 

1.3 deadline调度参数

对于redhat linux建议 read_expire = 1/2 write_expire,对于大量频繁的小文件I/O负载,应当这两者取较小值。更合适的值,需要通过实验测试得到。

echo 500 > /sys/block/sdb/queue/iosched/read_expire

echo 1000 > /sys/block/sdb/queue/iosched/write_expire

 

1.4 readahead 预读扇区数

预读是提高磁盘性能的有效手段,目前对顺序读比较有效,主要利用数据的局部性特点。比如在我的系统上,通过实验设置通读256块扇区性能较优。

blockdev --setra 256 /dev/sdb

 

2、EXT3文件系统参数

2.1 block size = 4096 (4KB)

mkfs.ext3 -b指定,大的数据块会浪费一定空间,但会提升I/O性能。EXT3文件系统块大小可以为1KB、2KB、4KB。

 

2.2 inode size

这是一个逻辑概念,即一个inode所对应的文件相应占用多大物理空间。mkfs.ext3 -i指定,可用文件系统文件大小平均值来设定,可减少磁盘寻址和元数据操作时间。

 

2.3 reserved block

mkfs.ext3 -m指定,缺省为5%,可调小该值以增大部分可用存储空间。

 

2.4 disable journal

对数据安全要求不高的应用(如web cache),可以关闭日志功能,以提高I/O性能。

tune2fs -O^has_journal /dev/sdb

 

3、mount参数

3.1 noatime, nodirtime

访问文件目录,不修改访问文件元信息,对于频繁的小文件负载,可以有效提高性能。

 

3.2 async

异步I/O方式,提高写性能。

 

3.3 data=writeback (if journal)

日志模式下,启用写回机制,可提高写性能。数据写入顺序不再保护,可能会造成文件系统数据不一致性,重要数据应用慎用。

 

3.4 barrier=0 (if journal)

barrier=1,可以保证文件系统在日志数据写入磁盘之后才写commit记录,但影响性能。重要数据应用慎用,有可能造成数据损坏。

 

4、小结

以/dev/sdb为例,优化操作方法如下,参数请自行调整。

sdparm -s WCE=1, RCD=0 -S /dev/sdb

echo deadline > /sys/block/sdb/queue/scheduler

echo 500 > /sys/block/sdb/queue/iosched/read_expire

echo 1000 > /sys/block/sdb/queue/iosched/write_expire

blockdev --setra 256 /dev/sdb

 

mkfs.ext3 -b 4096 -i 16384 -m 2 /dev/sdb1

tune2fs -O^has_journal /dev/sdb1

 

mount /dev/sdb1 /cache1 -o defaults,noatime,nodirtime,async,data=writeback,barrier=0 (if with journal)

mount /dev/sdb1 /cache1 -o defaults,noatime,nodirtime,async (if without journal)

 

 

  • 11
    点赞
  • 4
    评论
  • 70
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 点我我会动 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值