一 CPU 调优
1 系统拓扑
1 概述
在现代计算机技术中,大部分的系统都是拥有多个处理器的,多个处理器之间的连接并连接其他资源则需要通过系统拓扑来调节以产生影响
2 现代计算机技术的两种拓扑类型
1 SMP(对称多处理器)
SMP(对称多处理器)拓扑允许所有的处理器同时访问内存,然而,由于内存访问权限的共享性和平等性,固然会迫使所有的CPU和SMP系统序列化的内存访问权限局限性能加,目前这种情况是不被接受的,因此,现在服务器系统都是NUMA(非一致性内存访问)机制。
2 NUMA 拓扑(非一致性内存访问机制)
比起 SMP 拓扑,NUMA(非一致性内存访问)拓扑是近来才开发的,在NUMA系统中,多个处理器物理分组至一个socket,每个socket都由一个专用内存区,对该内存进行本地访问的服务器系统称为一个节点。
同一个节点上的服务器能够高速访问该节点的存储体,但访问其他节点的存储体速度就比较慢,因此,访问非本地存储体会造成性能的损失。
3 NUMA 拓扑调节注意事项
考虑到性能损失,服务器执行应用程序时,NUMA 拓扑结构系统中对性能敏感的应用程序应访问同一节点的内存,并且应尽可能地避免访问任何远程内存。
因此,在调节 NUMA 拓扑结构系统中的应用程序性能时,重要的是要考虑这一应用程序的执行点以及最靠近此执行点的存储体。
在 NUMA 拓扑结构系统中,/sys 文件系统包含处理器、内存及外围设备的连接信息。
/sys/devices/system/cpu 目录包含处理器在系统中相互连接的详情。 /sys/devices/system/node 目录包含系统中 NUMA 的节点信息以及节点间的相对距离。
4 确定系统拓扑结构
1 使用 numactl –hardware 指令描述系统的拓扑结构
[root@python ~]# numactl --hardware
available: 1 nodes (0) # 内存只有一个
node 0 cpus: 0 1 2 3
node 0 size: 4095 MB
node 0 free: 177 MB
node distances:
node 0
0: 10
2 使用 lscpu 指令来查询
其指令由util-linux 数据包提供,包括CPU体系结构信息,如CPU数量,线程数,内核数,socket数量以及NUMA节点数等。
[root@python ~]# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 2
座: 2
NUMA 节点: 1
厂商 ID: GenuineIntel
CPU 系列: 6
型号: 158
型号名称: Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz
步进: 9
CPU MHz: 3408.003
BogoMIPS: 6816.00
虚拟化: VT-x
超管理器厂商: VMware
虚拟化类型: 完全
L1d 缓存: 32K
L1i 缓存: 32K
L2 缓存: 256K
L3 缓存: 6144K
NUMA 节点0 CPU: 0-3
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ibrs ibpb stibp tpr_shadow vnmi ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec arat spec_ctrl intel_stibp arch_capabilities
2 调度
系统调度器决定运行线程的处理器和运行的时间。但由于调度器主要关注的是保持系统繁忙,因此可能不会为应用程序的性能而对线程进行最佳调度。
例,在NUMA系统中,一个处理器在节点B可用,一个应用程序在节点A运行,要使在节点B的处理器保持忙碌,调度器会把应用程序的一个线程转移到节点B。但是,线程上的应用程序仍然需要访问在节点A的内存。由于该线程目前在节点B运行,并且对于此线程来说节点A的内存已不再是本地内存,访问起来就要花更长的时间。较于在节点A等待可用的处理器,并且在能够进行本地内存访问的源节点上执行线程,此线程在节点B结束运行可能就更加费时。
1 内核滴答信号
滴答信号: 早起Linux 版本中,Linux内核会定期终端每个CPU已查看需要完成的任务,查看的结果用来决定进程调度及负载均衡,这便是滴答信号
缺点:此标记不会考虑内核是否有任务要执行,这使得即使空闲的内核也会被迫定期进入高能状态,这阻止了系统有效的利用x86代处理器的深睡眠状态
按需中断:
默认的redhat 6和7内核不再中断趋于低功率状态的空闲CPU, 当一个或几个任务在运行时,按需中断取代了定时中断,使得CPU可以更长久的处于空闲状态或低功率状态用以减少电量的消耗。
动态无时钟设置:
Linux redhat 7 提供一种动态的无时钟设置(nohz_full),通过用户空间的任务来减少内核干扰以进一步改善其确定性。这一设置可以在指定的内核中通过 nohz_full 内核参数来启用。当这一设置在一个内核中启用时,所有的计时活动将会被移动至无延迟敏感性的内核。这对于高性能计算和实时计算工作负载来说都很有用,因为其用户空间任务对由于内核计时器滴答信号造成的微秒级的延迟尤为敏感。
2 中断请求管理(Interrupt ReQuest)
中断请求或 IRQ 是请求及时关注的信号,是从硬件发送至处理器的。系统中的每个设备都分配到一个或多个 IRQ 号,以便能发送独一的中断信号。当启用中断时,收到中断请求的处理器会立即暂停执行当前应用程序线程,这是为了处理该中断请求。 因为中断了正常的运行,高中断率会严重降低系统性能,但减少中断事件是可能的,可以设置中断关联或发送一批低优先率的中断(“组合中断”)来处理此种情况。
3 监控和诊断性能问题
1 turbostat
Turbostat 在规定的间隔中给出计时器的结果以协助管理员识别服务器异常,例如过度耗电,无法进入深睡 眠状态或是创建了不必要的系统管理中断(SMIs)。
turbostat 工具是 内核工具 数据包的一部分。支持在 AMD 64 和 Intel® 64 处理器的系统中使用。需要 root 特权来运行,处理器支持时间戳计时器以及 APERF 和 MPERF 型号的特定寄存器。
2 numastat
numastat 工具会列举每个 NUMA 节点内存数据给所有的进程和操作系统,并会告知管理员进程内存是散布于系统还是集中于某个节点。
通过处理器的 top 输出进行交互参照 numastat 输出,以确认进程线程是在同一个节点运行,此节点是进程内存分配节点。
[root@centos8 ~]# numastat
node0
numa_hit 4372424
numa_miss 0
numa_foreign 0
interleave_hit 19604
local_node 4372424
other_node 0
numa_hit 为这个节点成功的分配尝试次数
numa_miss 由于在目的节点中内存较低而尝试为这个节点分配到另一个节点的数目,每个numa_miss事件都在另一个节点中有对应的numa_foregin 事件。
numa_foreign 最初要为这个节点但最后分配另一个节点的分配数,每个numa_foregin 事件都在另一个节点中有对应的numa_miss 事件
3 /proc/中断
/proc/interrupts 文件列举了从一个特殊的 I/O 设备发送至各处理器的中断数量,显示了中断请求 (IRQ)数量、系统中各处理器处理该类型中断请求的数量,发送的中断类型以及以逗号分隔开的回应所列中断请求的设备列表。
如果一个特定的应用程序或是设备生成大量的中断请求给远程处理器处理,其性能就会受到影响。这种情况 下,当应用程序或设备在处理中断请求时,可以在同一节点设置一个处理器,以此来缓解性能不佳的状况。将 中断处理分配给特定处理器的方法.
4 配置建议
默认情况下,Redhat 7 使用无时钟内核,其不会中断空闲CPU来减少用电量,并允许较新的处理器利用深睡眠状态。
红帽企业版 Linux 7 同样提供一种动态的无时钟设置(默认禁用),这对于延迟敏感型的工作负载来说是很有帮助的,例如高性能计算或实时计算。
5 配置内核滴答信号时间
要启用特定内核中的动态无时钟性能,在内核命令行中用 nohz_full 参数进行设定。在16 核的系统中,设定 nohz_full=1-15 可以在 1 到 15 内核中启用动态无时钟内核性能,并将所有的计时移动至唯一未设定的内核中(0 内核)。这种性能可以在启动时暂时启用,也可以在 /etc/default/grub 文件中永久启用。 要持续此性能,请运行 grub2-mkconfig -o /boot/grub2/grub.cfg 指令来保存配置。
启动动态无时钟性能需要一些手一动管理
当系统启动时,必须手动将rcu线程移动到对延迟不敏感的内核,这种情况下为0内核。
for i in `pgrep rcu` ; do taskset -pc 0 $i ; done
在内核命令行上使用 isolcpus 参数来将特定的内核与用户空间任务隔离开。 可以选择性地为辅助性内核设置内核回写式 bdi-flush 线程的 CPU 关联:
echo 1 > /sys/bus/workqueue/devices/writeback/cpumask
验证动态无时钟配置是否正常运行,执行以下命令,其中 stress 是在 CPU 中运行 1 秒的程序。
perf stat -C 1 -e irq_vectors:local_timer_entry taskset -c 1 stress -t 1 -c 1
默认的内核计时器配置在繁忙 CPU 中显示1000 次滴答记号:
# perf stat -C 1 -e irq_vectors:local_timer_entry taskset -c 1 stress -t 1 -c 1 1000 irq_vectors:local_timer_entry
动态无时钟内核配置下,用户只会看到一次滴答记号:
# perf stat -C 1 -e irq_vectors:local_timer_entry taskset -c 1 stress -t 1 -c 1
1 irq_vectors:local_timer_entry
6 设置硬件性能策略
x86_energy_perf_policy 工具允许管理员定义性能与能效的相对重要性。当处理器在性能与能效间权衡选 择时,此信息可用来改变支持这一特征的处理器。
默认情况下适用于所有在 performance 模式下的处理器,它要求处理器的支持,由 CPUID.06H.ECX.bit3 显示,且必须在有 root 特权的情况下运行。 x86_energy_perf_policy 由 kernel-tools 数据包提供。如何使用 x86_energy_perf_policy
7 使用taskset 设置处理器关联
taskset 工具由 util-linux 数据包提供。Taskset 允许管理员恢复和设置进程中的处理器关联,或通过特定的 处理器关联来启动一个进程。
1 使用 taskset 设置CPU的亲和性
taskset搜索并设定运行进程的CPU亲和性(根据进程ID),他还可以用于启动给CPU亲和性的进程,这个就可以将指定的进程与指定的CPU或者一组CPU进行捆绑,但taskset不保证本地内存分配。
如果想需要本地内存分配给额外性能利益,则建议使用numacl
CPU的亲原形使用位掩码表示,最低位对应第一个逻辑CPU,且最高位对应最后一个逻辑CPU,这些掩码通常是十六进制,因此 0x00000001 代表处理器0 表示为0001 0x00000009 代表处理器3 和 1 表示为1001
设置CPU和进程的亲和性
要想设定运行进程的CPU亲和性,执行 taskset -p mask pid 进行处理
要启动给定亲和性的进程,执行
taskset mask --program
-c 指定绑定在哪个cpu上
taskset -c 0,1,2,3 --myprogram
查看进程运行在哪个CPU上
ps axo pid,psr
PSR 运行在哪个处理器上
ps axo pid,psr | grep pid
上述绑定方式只能实现一个进程运行在这个CPU上,但不能保证别的进程不运行在对应的CPU上,如果需要,必须在操作系统日志启动之前执行某些进程目前不能使用,隔离出来.
[root@master ~]# cat /etc/rc.local
taskset -c 1,2 httpd
[root@master ~]# ps axo pid,psr | grep -E "1296|1298"
1296 2
1298 2
此方式能保证进程运行在该CPU,但不能保证CPU中的内存数据运行在本地中
8 使用numactl 管理 NUMA 关联
管理员可以通过特定的调度或者内存安装策略来使用Numactl 运行进程,numactl也可以为共享内存片段或文件设置永久性策略,并设置处理器关联和进程的内存关联
在NUMA系统系统中,处理器和内存条之间的距离越大,其访问内存条的速度就越慢,应该讲对性能敏感的程序配置为可以从最近的内存条分配内存,最好是使用在同一 NUMA 节点的内存和 CPU
注意事项
对性能敏感的多线程应用程序经配置后在特定的 NUMA 节点上运行会比在特定的处理器上运行好处更多。这是否适合则取决于用户系统及应用程序的需求。如果多个应用程序线程访问同一缓存数据,那么对那些线程进行配置,使其在同一处理器上运行可能是合适的。但是,如果在同一处理器上运行的多线程访问及缓存的是不同数据,那么每个线程可能会收回之前线程访问的缓存数据。这就意味着每个线程会“缺失”缓存,会浪费运行 时间来从磁盘中获取数据并在缓存中替代它。
/sys 文件系统包含有CPU,内存和外设,其连接是通过.NUMA进行互联的,特别是/sys/devices/system/cpu 目录中包含有关系统的CPU是图和处理连接信息的,
/sys/devices/system/node 目录包含有关系统中NUMA 节点以及节点间的相对距离的信息
/proc 内核级别的信息
/sys 硬件,内存相关的信息
numactl参数详解
–show
显示当前进程的NUMA策略设置
–hardware
显示系统中可用节点的清单
–membind 内存亲原性
只从指定节点分配内存,当使用这个参数时,如果这些节点中的内存不足则分配会失败,这个参数的用法是
Numactl –membind=nodes program ,其中nodes 是您要从中分配内存的节点列表,program 是要从哪个节点分配内存的程序,节点号可以采用逗号分开的列表,范围或者两者的结合方式提供,
–cpunodebind 绑定CPU和内存
只执行属于指定节点的CPU中的命令(及其子进程),这个参数的用法是numactl –cpunodebind=nodes progrpm ,其中nodes 是指定程序要捆绑的CPU 所属节点列表,节点号可以采用逗号分开的列表,范围或者两者的结合方式提供
–physcpubind
只执行指定CPU 中的命令,这个参数的用法是numactl –physcpubind=cpu program,其中CPU 是用逗号分隔开的物理CPU 号列表,这些数据在/proc/cpuinfo 的processor字段中显示,program是只在那些CPU中执行的程序,还要将CPU指定为与当前cpuset 相关联
–localalloc
指定永远要在当前节点中分配的内存,将进程调度到那个CPU上,这个进程就在对应的内存节点上运行和存储数据
–preferred
在可能的情况下分配内存到指定节点中的内存,如果内存无法分配到指定的节点,则返回其他节点。
Numactl --preferred=nodes
必须在启动程序时指定
必须在启动脚本上执行
[root@python ~]# numactl --show
policy: default
preferred node: current (当前节点)
physcpubind: 0 1 2 3
cpubind: 0
nodebind: 0
membind: 0
9 使用 numad 进行自动化 NUMA 关联管理
1 概述
numad 是一种自动化的 NUMA 关联管理后台程序。它对系统中的 NUMA 拓扑及资源用量进行监控,以便动 态地改善 NUMA 资源配置及管理。
numad 也同样提供预先安置咨询服务,这一服务可以通过不同的作业管理系统来查询,并为处理器 CPU 的 初始绑定及内存资源提供帮助。无论 numad 是以可执行程序或服务在运行,这一预先安置咨询都可用。
根据系统负载,numad 可对基本性能有50%的提高,要达到此性能的优势,numad会周期性的访问 /proc 文件系统中的信息以便架空每个节点中可用的系统资源,该守护进程然后会尝试在有足够内存和CPU资源的NUMA节点中放置大量进程已优化NUMA性能,目前进程管理阈为至少是一个CPU的50%,且至少有300MB内存,numad会尝试维护资源换使用水平,并在需要时通过在NUMA节点间一共进程平衡分配。
numad 还提供预布置建议服务,可以通过各种任务管理系统进行查询以便提供CPU起始捆绑以及进程内存资源的支持,这个预布置建议服务无论系统中是否运行numad都可以使用。
2 numad 有两种使用方式
1 作为服务使用
将 numad 作为服务运行时,它尝试基于当前系统的工作负载来动态调整系统。其活动记录在 /var/log/numad.log。 如需启动服务,运行: # systemctl start numad.service 如需重启后服务持久,运行:
# chkconfig numad on
2 作为可执行文件使用
在命令行使用 numad
将 numad 作为执行表使用,只需运行:
numad
numad 运行的时候,其活动被记录在 /var/log/numad.log。
它会持续运行直到被以下命令终止:
numad -i 0
终止 numad 不会移除它所做的提高 NUMA 关联的变更。如果系统使用有显著的变化,再次运行 numad 能 调整关联来提高新条件下的性能。
如需将 numad 管理限制为特定进程,
用下列选项来启动它:
numad -S 0 -p pid -p
pid该选项将指定的 pid 添加到显式的包含列表中。当指定的进程达到 numad 进程的显著门限值,指 定的进程才会被管理。
-S 0它将进程扫描的类型设置为 0,这会将 numad 管理限制到显式包的进程。
4 调度策略
1 概述
Linux 调度器执行大量的调度原则,以此决定线程运行的位置和时长。调度原则主要有两类:普通原则和实时原则。普通线程用于普通优先级任务,实时原则用于具有时效性且必须无中断完成的任务。
实时线程不受时间间隔的控制,这意味着它们将一直运行直至它们阻拦、退出、主动让步或是被更高优先权的线程预先安置。最低优先权的实时线程会先于其他普通原则的线程进行调度。
2 调度原则
调度程序复制保证系统中的CPU处于忙碌状态,Linux 调度程序采用调度策略,他可以决定何时以及在具体CPU何种线程运行的时间
1 实时策略(优先级进行扫描)
1 SCHED_FIFO
静态优先调度策略,每一个线程有固定的优先级权限,该调度程序根据优先级权限顺序扫描,sched_fifo线程列表,并调度准备好运行的最高优先权限的线程,这个线程会运行到他阻断,退出或者被更好的线程抢占准备运行的时候,这一策略建议无法运行较长时间且具有时效性的任务使用
即使是最低优先权的实时线程也会比非实时策略线程提前调度,如果只有一个实时线程,则sched_fifo优先权值就无所谓了,只有那些内核线程的优先级才是实时的优先级,一个 SCHED_FIFO 线程的优先级级别可以是 1 至 99 之间的任何整数,99 是最高优先 级。红帽建议一开始使用较小的数字,在确定了延迟问题后再增加优先级。
由于实时线程不受时间间隔的控制,红帽不推荐设置 99 优先级。这会使同优先级的进程成为迁移线程 或监控线程,如果线程进入一个计算机回路且这些线程被阻拦,它们将无法运行。这种情况下,单处理 器系统最终会暂停。
管理员可以限制 SCHED_FIFO 的带宽以防止实时应用程序的程序员启用独占处理器的实时任务。
/proc/sys/kernel/sched_rt_period_us
该参数以微秒为单位来定义时间,是百分之百的处理器带宽。默认值为 1000000 μs, 或1秒。
/proc/sys/kernel/sched_rt_runtime_us该参数以微秒为单位来定义时间,用来运行实时线程。默认值为 950000 μs, 或0.95秒
2 SCHED_RR
轮训调度,也会为sched_rr 线程提供1-99之间的固定优先权,但有相同优先权的线程使用特定或者时间片轮训方式进行调度,sched_rr_get_interval 系统调用所有时间片返回的数值,但用户无法设定时间篇持续大时间,这个策略对于具有相同优先级运行的多线程是有帮助的。
修改进程的实时优先级
[root@python ~]# chrt -h
Show or change the real-time scheduling attributes of a process.
Set policy:
chrt [options] <priority> <command> [<arg>...]
chrt [options] --pid <priority> <pid>
Get policy:
chrt [options] -p <pid>
Policy options:
-b, --batch set policy to SCHED_BATCH
-d, --deadline set policy to SCHED_DEADLINE
-f, --fifo set policy to SCHED_FIFO
-i, --idle set policy to SCHED_IDLE
-o, --other set policy to SCHED_OTHER
-r, --rr set policy to SCHED_RR (default)
Scheduling options:
-R, --reset-on-fork set SCHED_RESET_ON_FORK for FIFO or RR
-T, --sched-runtime <ns> runtime parameter for DEADLINE
-P, --sched-period <ns> period parameter for DEADLINE
-D, --sched-deadline <ns> deadline parameter for DEADLINE
Other options:
-a, --all-tasks operate on all the tasks (threads) for a given pid
-m, --max show min and max valid priorities
-p, --pid operate on existing given pid
-v, --verbose display status information
-h, --help 显示此帮助并退出
-V, --version 输出版本信息并退出
chrt 指定优先级 -p 指定pid
如果不指定使用的,则默认使用RR调度策略
2 一般策略(用户进程)
守护进程和批处理进程
交互进程
SCHED_OTHER 或者 SCHED_NORMAL
SCHED_OTHER redhat 7 默认调度策略,该策略使用完全公平调度程序(CFS)提供对所有使用此策略线程的提供公平访问时间段,CFS建立了动态优先权限列表,部分是根据每个进程线程的niceness 值,这样可为用户提供一些间接控制进程优先权的权利,但这个动态优先权列表只能由CFS直接修改,此调度算法适用于具有大量线程或数据吞吐量优先时最有用,因为其能够随着时间而更为有效的调度线程。
用于低优先权任务
SCHED_BATCH
SCHED_IDLE
3 常用的调度策略
sched rr
chrt -r
1-99 数字越大,优先级越高
sched_other
自动内核自动提供动态优先级手动 nice renice
100-139 数字越小,优先级越高
4 策略选择
为程序线程选择正确的调度程序策略不总是那么直接了当的任务,通常应在关键时间或者需要迅速调度期望不能延长运行时间的重要任务中实施策略,一般策略通常可以产生比实时策略好的数据流量结果,因为它们让调度进程更有效的运行(及就是它们不需要经常重新调度占先的进程),
如果需要管理大量进程,且担心数据流量(每秒的网络数据包,写入磁盘等),那么请使用SCHED_OTHER,并让系统为你管理CPU
如果担心事件响应时间延迟,则使用SCHED_FIFO,如果只有少量的线程,则可以考虑隔离CPU插槽,并将线程移动到那个插槽的核中以便没有其他线程与之竞争。
3隔离CPU
1 isolcpus 开机隔离CPU
用户可以使用isolcpus开机参数来从调度器隔离一个或多个CPU,以此防止调度在此CPU上调度任何用户空间的线程。
一旦CPU被隔离,用户需要手动分配进程至被隔离的CPU,或者使用CPU相关系统呼叫或者numactl命令
将系统中第三和第六 CPU 隔离至第八 CPU,添加如下至内核命令行:
isolcpus=2,5-7
2 Tuna 工具隔离CPU
用户也可使用 Tuna 工具来隔离CPU。Tuna 可以随时隔离 CPU,不仅仅局限于启动时。但这种隔离方法与 isolcpus 参数略有不同,并且目前尚未实现与 isolcpus 相关的性能收益。
在超过 32 个处理器的系统中,用户须将 smp_affinity 的值限定为分散的 32 位组。例如,如果一开始只 想使用 64 位处理器系统中的 32 位处理器来处理一个中断请求,可以运行:
echo 0xffffffff,00000000 > /proc/irq/IRQ_NUMBER/smp_affinity
3 使用 tuna 配置 CPU,线程和中端关联
Tuna 能够控制CPU,线程及中断关联,并能够给其所能控制的每类实体提供大量操作,
要从一个或多个特定的 CPU 中移除所有线程,请运行如下命令,使用想要隔离的 CPU 数量来替换 CPUs。
tuna --cpus CPUs --isolate
要在可运行特定线程的 CPU 列表中加入一个 CPU,请运行如下命令,使用想要加入的 CPU 数量来替换 CPUs。
tuna --cpus CPUs --include
要将一个中断请求移动至特定的 CPU,请运行如下命令,用 CPU 数量替换 CPU,用想要移动且使用逗号分 隔的中断请求列表替换 IRQs。
tuna --irqs IRQs --cpus CPU --move
此外,用户可以使用如下命令来找到所有 sfc1* 模式的中断请求。
tuna -q sfc1* -c7 -m -x
要改变一个线程的策略和优先级,请运行如下命令,使用想要改变的线程替换 thread,使用需要的线程运行策 略名称替换 policy,用从 0(最低优先级)至 99(最高优先级)间的一个整数替换 level。
tuna --threads thread --priority policy:level
4 中断和中断请求(IRQ) 调解
RIQ中断请求是用于服务的请求,从硬件层面发出,可使用专用硬件线路或者跨硬件总线的信息数据包发出中断。
启用中断后,接受IRQ 后会提示切换到中断上下文,内核中断调度代码会搜索IRQ 号码机器关联的注册中断服务路由ISR 列表,并按顺序调用ISR,ISR 会确认中断并忽略来自同一IRQ 的多余中断,然后在延迟的句柄中排队完成中断处理,并忽略以后的中断来结束ISR
[root@master ~]# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
0: 148 0 0 0 0 0 0 0 IO-APIC-edge timer
1: 13 0 0 0 0 0 0 0 IO-APIC-edge i8042
8: 1 0 0 0 0 0 0 0 IO-APIC-edge rtc0
/proc/interrupts 文件列出每个IO 设备中每个CPU 的中断数,每个CPU 核处理的中断数,中断类型,。以及用逗号分开的注册为接受中断的驱动程序列表
IRQ 有一个关联的“类似”属性 smp_affinity ,该参数可以定义运行IRQ 执行ISR 的CPU和,文件中,可以提高程序的性能,方法是为一个或多个具体的CPU 核分配中断类似性和程序线程类似性,这可让缓存在指定的中断和程序线程之间共享
具体IRQ 数的中断近似性值是保存的相关的/proc.irq.IRE_NUMBER/smp_affinity 文件中,可以作为root 用户查看并修改该值,保存在这个文件中的值是一个十六进制字节掩码,代表系统中所有CPU 核。
[root@master ~]# grep eth0 /proc/interrupts
18: 24909 0 0 0 0 0 0 0 IO-APIC-fasteoi eth0
[root@master ~]# cat /proc/irq/18/smp_affinity f 表示所有CPU
00000000,00000000,00000000,000000ff
对于某些特定的硬件,在其注册时就会保存在某些CPU 上
对于某些公共的硬件,如网卡,硬盘等有可能是内核不断的调度的
大多数硬件都是CPU0 上处理的
Smp_affinity 的默认值是f,及可为系统中的任意CPU 提供IRQ,将这个值设定为1,如下
[root@master ~]# echo 1 > /proc/irq/18/smp_affinity
[root@master ~]# cat /proc/irq/18/smp_affinity
00000000,00000000,00000000,00000001
隔离中断
将某些在指定的CPU上的中断进行调整到另外的cpu上,然后再进行绑定
[root@master ~]# echo 1 > /proc/irq/18/smp_affinity
[root@master ~]# cat /proc/irq/18/smp_affinity
00000000,00000000,00000000,00000001
某特定进程绑定在特定CPU上,且该CPU 不处理任何其他请求,也不处理任何中断,避免中断上下文和进程上下文之间的切换
二 内存调优
1 注意事项
对于适中的工作负载,红帽企业版 Linux 7 会默认优化。如果用户的应用程序或用例需要大量的内存,那么改变系统处理虚拟内存可以提高应用程序的性能。
2 页面和内存管理
1 页面管理
物理内存管理区称为页面,每一个页面的物理位置都映射到一个虚拟位置以便于处理器能够访问内存,这种映射存储于一种叫做页面表的数据结构中。物理内存被组织成叶匡,而线性地址被组织成页面,数据的存放都是以页面的格式进行定义的,页面的数据有可能被映射到非连续的物理叶匡中,
默认情况下,一个页面大约有4kb,1M 内存等于256个页面,1GB 内存等于256000个页面,CPU有内嵌的内存单元,这些单元中包含着这些列表,每个页面都使用也表条目参考。,由于页面的默认大小很小,因此用户需要很多页面来管理大量内存,其页面表只能存储有限的地址映射,增加其存储地址映射的数量既昂贵又困难,因此要考虑到将性能等级保持在内存需求范围内,32 位系统一般支持4k的页面叶匡和4M的,64 位 4k 和 2M 的叶匡。
2 超大转义后备缓冲器(huge TLB)
将物理内存地址转义为虚拟内存地址是内存管理的一部分,物理地址和虚拟地址的映射关系保存在名为页表的数据结构中,因为每个地址映射读取页表会很消耗时间和资源,所以最近使用的地址都有缓存,这个缓存就是转移后备缓冲器 .
但TLB 只能缓存大量的地址映射,如果所要求的地址映射没有在TLB中,则必须扔读取页表已决定物理到虚拟地址的映射,这就是TLB缺失,因为内存要求与用来缓存TLB 中地址映射之间的关系,所以有大内存要求的程序比使用较少内存的程序更容易受TLB缺失的影响,因为每一个缺失都涉及页表读取,因此尽量避免这些缺失很重要。
超大转移后备缓冲器(huge TLB)可以很大片管理内存,以便一次可以缓存更多地址,这样可以减少TLB 缺失的可能性,进而改进有大内存要求的程序的程序性能。
红帽企业版 Linux 提供大型转换后背缓冲区 (大型 TLB),可以将内存分为大片段进行管理。这使大量的地址映射能同时进行缓存,以此降低 TLB 缺失的可能性,并提高需要大内存的应用程序的性能。
3 大内存和透明页
当数据访问时,是装入时长访问的数据,而不是装入所有数据,此时如果需要访问其他没有被装载的数据,则会发生数据异常,此时需要通过IO的方式来进行查询处理
对于非常吃内存的进程,进行开启其大内存页的功能,这就是一种调优方式
让系统管理大量内存的两种方式
1 增加硬件内存管理单元的页表数
2 增加大页面第一种方式很贵,现在的处理器中的硬件内存管理单元只支持数百或者数千条页条目,另外适用于管理数千页面硬件和内存管理算法可能无法很好的管理百万甚至数亿页面,这会造成性能问题,但程序序号使用比内存管理单元更多的页面,该系统就会回退到缓慢的基于软件的内存管理,从而造成整个系统运行缓慢。
超大页面时2MB和1GB大小的内存块,2MB使用的页表可管理多GB,而1GB页是TB内存的最佳选择
超大页面必须在引导时分配,他们很难手动管理,且经常需要更改代码以便可以有效使用,因此红帽企业版Linux 也部署了透明超大页面(THP)
THP 是一个提取层,可自动创建。管理和使用超大页面的大多数方面超大页面必须引导时配置,而透明大页面可以随时配置
THP 系统管理员和开发者减少了很多使用超大页面的复杂性,因为THP的目的是改进性能,所以其开发者已在各种系统、配置和负载中测试并优化的THP ,这样可让THP 的默认设置改进大多数系统配置性能
Varish 和透明大页面不兼容,大页面可能会导致内存泄露
Varish 在2M的页面上性能很一般
透明大页面管理职能用于异步内存段的管理
红帽企业版 Linux 通过静态大型分页来给每个页面管理大内存的能力,静态大型分页可以分配到1GB大小,但其难以管理,必须在启动时就分配好。
透明大型分页很大程度上是之余静态大型页面的一个自动选择。透明大型页面大小为 2 MB 且默认启动。它们有时会干扰对延迟敏感的应用程序,因此常常在延迟严重时被禁用。
2 监控及诊断性能问题
红帽企业版Linux 7 提供大量有用工具来监控系统性能与系统用内存相关的性能问题
1 vmstat 监控内存使用量
Vmstat 由procps-ng 数据包提供,输出用户系统进程,内存,网页,字块输入/输出,中断以及CPU的活动等报告,
具体见下:
https://blog.51cto.com/11233559/2152153
2 用 valgrind 分析应用程序的内存使用量
1 安装
Valgrind 是一个为用户提供空间二进制文件测量方法的框架。它包含大量的工具来概述和分析程序性能。本章列出的 valgrind 工具能帮助用户检测内存错误,例如未初始化的内存使用和不适当的内存分配及解除分配。
要使用 valgrind 或其工具,请安装 valgrind 数据包:
yum install valgrind
2 memcheck
memcheck 是默认的valgrind工具,其检测并报告出大量难以检测和诊断到的内存错误,如
不应发生的内存访问
使用未定义或者未初始化的值
不正确的释放堆地址
指示字重叠
内存泄漏
memcheck 只能报告这些错误,但并不能阻止它们发生,如果程序以通常会引起段错误的方式来访问内存的话,段错误仍然会发生,但memcheck会在发生错误之前立即记录一条信息
由于 memcheck使用测量工具,通过memchek执行的应用程序会比平常运行起来慢10-30倍。
要在应用程序上运行 memcheck, 请执行以下指令:
valgrind --tool=memcheck application
用户也可以使用以下选项来使 memcheck 的输出集中在特定的问题类型上。
3 参数详解
–leak-check
在应用程序结束运行后,memcheck 会搜索内存泄露问题。默认值为 –leakcheck=summary,在找到内存泄露时会显示其数量。用户可以指定 –leak-check=yes 或 –leak-check=full 来输出每个泄露问题的详情。禁用请设定 –leak-check=no。
–undef-value-errors
默认值为 –undef-value-errors=yes,使用未定义的值时会报错。用户还可设定 –undef-value-errors=no ,这将禁用此报告并略微提高 Memcheck 的速度。
–ignore-ranges
在查看可寻址内存时指定一个或多个 memcheck 应忽略的范围,例如, –ignoreranges=0xPP-0xQQ,0xRR-0xSS。
3 cache grind
使用 cache grind 分析缓存使用量
cachegrind 会模拟应用程序与系统缓存层析结构和分支预测器之间的交互作用,他会追踪模拟的以及指令和数据缓存使用情况,以此检测出该级缓存与代码间不良的交互作用。它也会追踪最后一级缓存(第二或第三极)以便追踪内存访问。这样的情况下,使用 cachegrind 的应用程序运行起来会比通常慢 20-100 倍。
Cachegrind 会收集应用程序执行期间的统计数据,并且将概要输出至操作台。要在应用程序中运行
cachegrind ,请执行以下指令:
valgrind --tool=cachegrind application
用户也可以使用以下选项来让 cachegrind 的输出集中在一个特定的问题上。
参数详解
–I1
指定大小、关联性以及第一级指令缓存行大小的方法如下:–I1=size,associativity,line_size。
–D1
指定大小、关联性以及第一级数据缓存行大小的方法如下:–
D1=size,associativity,line_size.。
–LL
指定大小、关联性以及最后一级缓存行大小的方法如下:–
LL=size,associativity,line_size。
–cache-sim
启用或禁用缓存访问和缺失数量的集合是默认启用的(–cache-sim=yes)。禁用此集合以及 –branch-sim 来使 cachegrind 不收集信息。
–branch-sim
启用或禁用分支指令及错误预测数量的集合是默认启用的(–branch-sim=yes)。禁用此集合以及 –cache-sim 来使 cachegrind 不收集信息。
Cachegrind 写入详细的分析信息至每个进程 cachegrind.out.pid 文件,其中, pid 是进程标识符。这一详细信息可以使用 cg_annotate 工具进行进一步处理,方法如下:
cg_annotate cachegrind.out.pid
Cachegrind 也提供 cg_diff 工具,可以更为容易地在代码变化前后对程序性能进行记录。要对比输出文
件,请执行以下命令:先用原始配置输出文件替代,再用后续配置输出文件替代。
cg_diff first second
4 使用massif分析堆栈空间
Massif 测量特定应用程序的堆空间。它测量可用空间和额外用来记录和调准的空间。massif 有助于用户了解减少应用程序内存使用的方法,以便提高运行速度,减少应用程序耗尽系统交换空间的可能性。使用massif 执行的应用程序运行起来比平常通常慢 20 倍左右。
要在一个应用程序中运行 massif,请执行如下命令:
valgrind --tool=massif application
用户也可以使用以下选项来将 massif 的输出集中在一个特定的问题上。
–heap
设定 massif 是否分析堆。默认值为 –heap=yes。要禁用堆分析可设置为 –heap=no。
–heap-admin
堆分析启用时要设定每个用于管理的数据块字节数。默认值为 8 字节。
–stacks
设定 massif 是否分析堆。默认值为 –stack=no 是由于堆分析会大大减缓 massif。将这一选项设置为 –stack=yes 来启用堆分析。要注意的是,massif 会假设主要的堆始于零值,这是为了更好地显示与所分析的应用程序相关的堆尺寸的变化。
–time-unit
设定 massif 收集分析数据的间隔。默认值为 i(执行指令)。用户也可以指定 ms(毫秒或实时)和 B(分配或收回的堆栈字节数)。检查分配的字节数有利于短期运行的应用程序及测试,因为对于不同的硬件来说,它是最具重复性的。
Massif 将分析数据输出至 massif.out.pid 文件中,该文件中的 pid 是指定应用程序的进程标识符。ms_print 工具将此分析数据绘成图表,以此显示执行应用程序的内存消耗,也包括峰值内存分配点负责分配的站点详情。要绘制 massif.out.pid 文件中的数据,请执行以下指令:
ms_print massif.out.pid
3 配置工具
1 简介
内存使用量往往是通过设置一个或多个内核的参数值来进行配置的,这些参数可以通过改变在/proc文件系统中的文件内容来进行暂时的设置,或者是通过设置系统核心参数工具来进行永久设置,此工具由procps-ng数据包提供
例如,要将 overcommit_memory 参数暂时设置为 1,请运行以下指令:
echo 1 > /proc/sys/vm/overcommit_memory
要永久设置这个值,请运行以下指令:
sysctl vm.overcommit_memory=1
暂时设置一个参数有利于决定此参数对系统的影响。用户可以在确定了参数值有预期的效果之后再将其设置为 永久值。
2 配置大页面
大页面依赖于连续的内存区域,因此最好在启动时,也就是内存变为判断之前就定义好大页面,为此,可添加一下参数至内核启动命令行:
hugepages
启动时在内核中定义 2MB 定值大页面的数量。默认值为 0。只有在系统拥有足够的物理持续性空闲 页面时才能进行分配(或是收回)大页面。此参数保留的页面不能用于其他目的。
此值可以在启动后通过改变 /proc/sys/vm/nr_hugepages 文件值来调节。 更多详情请参阅相关内核文档,默认安装于 /usr/share/doc/kernel-doc- kernel_version/Documentation/vm/hugetlbpage.txt 中。
/proc/sys/vm/nr_overcommit_hugepages
通过超量使用内存来定义系统所能创建和使用的最大数量的额外大页面。在此文件中写入任何非零 的值,表示系统包含此数目的大页面,在不变的页面池耗尽后,这些大页面便来自于内核的常规页 面池。由于这些额外的大页面是未使用过的,因此它们会释放并返回至内核的常规页面池中。
3 配置系统内存容量
虚拟内存参数
此处参数都早/proc/sys/vm中,除非另有标明
dirty_ratio: 一个百分比值,当整个系统内存的这一百分比值被修改时,系统会通过运行pdflush 将改动写入磁盘,默认是20%。
dirty_background_ratio: 一个百分比值,当整个系统内存的这一百分比值被修改时,系统会在后台将改动写入磁盘,默认是10%。
overcommit_memory: 定义用来决定接受或拒绝一个大内存请求的注意事项
默认值为0,默认情况下,内核执行探索发内存超量使用,是通过估算可用内存大小和由于太大而失败的请求来进行处理的,但是由于内存分配使用的是探索算法而不是精确算法,这一设置导致超载内存是可能的。
当这一个参数设置成1时,内核不执行内存超量使用处理,这增加了内存超量的可能性,但也提高了内存密集型任务的性能。
当这一参数设置成2时,内核拒绝请求,及请求的内存大于或等于总的可用交换空间,以及在overcommit_ratio中指定的物理RAM的百分比,这减少了超量使用内存的风险,但仅在系统交换空间大于物理内存时推荐此设置。
overcommit_ratio
当 overcommit_memory 设置为2时,设定所考虑的物理RAM的百分比,默认值为50.
max_map_count
定义一个进程可以使用的最大内存映射区域数量,默认(65530) 适用于大部分情况,如果应用程序需要映射超过此数量的文件,可增加此值。
min_free_kbytes
指定千字节的最小数量,使之在整个系统中都保持空闲,这是用来给每个低内存区决定一个合适的值,每一个低内存区都是按照其大小比例分配了大量保留的空闲页面。
警告:
极值会损坏用户的系统。将 min_free_kbytes 设置为一个极小的值以防止系统回收内存,回收内存会导致系统锁死,以及 OOM-killing 进程。但是,将 min_free_kbytes 设置过高 (例如,整个系统内存的 5–10% )会使系统立即进入一种内存不足的状态,导致系统花太多时间来回收内存。
oom_adj
在系统内存不足,并且panic_on_oom参数设置成0的情况下,oom_killer 功能会结束进程,直至系统可以恢复,从提高的oom_score 进程开始。
oom_adj 参数有助于确定一个进程的oom_score,此参数以每一个进程标识符为单位进行设置,值为-17时会禁用进程的oom_killer,其他有效值从-16到15 由一个调整过的进程而产生的进程会继续该进程的 oom_score。
swappiness
一个从 0 到 100 的值可以控制系统交换的程度。高值优先考虑系统效率,并在进程不活跃时主动交换物理内存耗尽的进程。低值优先考虑响应度,并且尽可能久地避免交换物理内存耗尽的进程,默认值为 60。
4 文件系统参数
此处中的参数都在/proc/sys/fs内,除非另有标明。
aio-max-hr
定义在异步输入/输出环境中允许的最大事件数量,默认值为65536,修改此值不会预分配或改变任何内核数据结构的大小。
file-max
定义内核分配最大的文件句柄数量,默认值与内核中的files_stat.max_files 值相匹配,将此值设置为最大值NR_FILE(8192,在红帽企业版Linux中)或是以下结果:
(mempages * (PAGE_SIZE / 1024)) / 10
增加此值可以解决由于缺少可用文件句柄而引起的错误
5 内核参数
此处中的参数都在/proc/sys/kernel内,除非另有标明。
msgmax
msgmax 以字节为单位,定义任何一个在信息队列中的信息可能的最大值,该值不能超过队列的大小(msgmnb),默认值为65536Z
msgmnb
以字节为单位,定义每一个信息队列的最大值,默认是65536
msgmni
定义信息队列标识符的最大数量(以及队列的最大数量),在64位架构的系统中,默认值为1985.
shmall
定义页面上共享内存的总量,这些内存是系统可以同时使用的shmmni
定义系统范围内最大的共享内存片段数量,在所有系统中默认值为4096
threads-max
定义系统范围内内核能同时使用的最大线程量,默认值与内核参数max_threads 相同,或为一下结果:
mempages / (8 * THREAD_SIZE / PAGE SIZE )
最小值为20
三 存储和文件系统
1 注意事项
存储和文件系统性能的合理设置很大程度上取决于存储目的,I/O和文件系统性能会受到下列因素的影响:
1 数据写入或者读取模式
2 数据重新排列与底层架构
3 块大小
4 文件系统大小
5 日志大小和位置
6 记录访问次数
7 确保数据可靠性
8 预取数据
9 预先分配磁盘空间
10 文件碎片
11 资源争用
2 固态硬盘
SSD(固态硬盘)使用闪存芯片而非旋转磁盘存储永久数据,它们为逻辑块地址内的全部数据提供恒定的访问时间,而且不会像它们旋转的对应物那样出现可测量的搜寻成本,每千兆字节的存储空间更昂贵且存储密度更好,但比HDD延迟时间短,吞吐量更大。
当在SSD上使用块接近磁盘容量,性能通常会降低,降低的程度因供应商的不同而异,在此情况下,所有设备性能都会降低,启用放弃有助于缓解性能降低。
默认I/O调度器和虚拟内存选项适用于SSD
3 I/O调度器
1 概述
I/O 调度决定I/O操作何时运行存储设备上以及运行多久,其也被称为I/O elevator(I/O升降机)
2 deadline
除了SATA 磁盘为所有的块设备的默认I/O调度器,deadline尝试为指向到达I/O调度器的请求提供有保障的延迟,该调度器适合大多数用例,尤其适用于读取操作比写入操作更频繁的请求。
将排队的I/O请求分类为读或者写批处理,并按照LBA递增顺序执行,默认设置下,读批处理优先于写批处理,这是因为应用更可能阻止读取I/O,批处理后,deadline检查写入操作因等待处理时间而处于多久的"饥饿"状态,并且适当的调度下一个读批处理或者写批处理,解决批处理的请求数量,发出写批处理的读批处理数量,以及请求过期前的时间量都是可以配置的。
3 cfg
默认调度只适用于标记为SATA 硬盘的设备,完全公平调度器,cfg,将进程分为三个独立的类别, 实时,尽其所能和空间,实时类别的进程总是先于尽其所能类别进程执行,而尽其所能类别进程总是在空闲类别进程之前执行。这意味着实时类别可以时其尽其所能和空闲进程等待处理器时间而忍受"饥饿",默认情况下,分配进程到尽其所能类别
cfg 使用历史数据来因此应用是否会在不就之后发出更多的I/O请求,如果将有更多的I/O请求,cfq空闲则会等待新的I/O,即使有来自其他进程的I/O在等待处理
因为有空闲趋势,cfg调度器不应用于连接不会引起大量搜寻的硬件,除非它为次目的而被调整,cfg调度器也不应用于连接其他断续工作型调度器。
cfg 行为是可高度配置的
4 noop
noop I/O调度器执行简单的FIFO(先进先出)调度算法,请求通过简单的最后选中的缓存数据在一般块层合并,对于使用最快存储的受CPU限制的系统,这是最佳的调度器
4 文件系统
1 XFS
XFS 是一个可靠的,且高度缩放的64位文件系统,是Linux redhat7 中默认的文件系统,XFS使用基于分区的分配,具有一些分配方案,包括预先分配和延迟分配,这两种都会减少碎片和辅助性能,它也支持促进故障恢复的元数据日志,当挂载并激活时,能够对XFS进行碎片化整理和放大,XFS支持最大容量可达500TB的文件系统。以及最大容量为8EB的文件偏移量。
2 Ext4
Ext4是Ext3文件系统的可缩放扩展,它的默认行为对大部分工作负载是最佳的,然而,它只支持最大容量为50TB的文件系统有一集最大容量为16TB的文件。
3 Btrfs(技术预览)
Btrfs 是提供缩放性,容错和方便管理的copy-on-write(写时复制)文件系统,它包括内置快照和RAID支持,通过数据和元数据校验来提供数据的完整性,它也是通过数据压缩提高性能及使用空间的效率,Btrfs作为一种技术预览,支持最大容量可达50TB的文件系统。Btrfs是最适合桌面存储和云存储,
4 GFS2
GFS2是具有极高可用性附加装置的一部分,为redhat 7 企业版提供簇文件系统支持,GFS2集群提供所有服务器一致的文件系统图像,允许服务器在单独共享文件系统中读取和写入。
GFS2 支持最大容量可达150TB的文件系统
5 格式化文件系统注意事项
1 概述
在设备格式化后,文件系统配置的部分决定不能改变,此处必须对格式化后的结果进行准确的预估
2 大小
按照工作负载创建合理大小的文件系统,按相应比例,较小的文件系统的备份次数也较少,且文件系统检查需要时间和内存也更少,然而,如果您的文件系统太小,性能将因为大量碎片化而降低
3 块大小
块是文件系统中的工作单位,块大小决定单个块能存储多少数据,也因而决定能够同时读写数据的最小量
默认块大小适用于大部分用例,然而,如果块大小和通常同时读写的数据数量一样大,或者略大时,文件系统将执行的更好,存储数据更加有效率,小文件仍将使用一个完整的块,文件分布在多个块中,会造成额外的运行时间开销,另外一些文件系统受限于一定数量的块,转而限制文件系统的最大尺寸
使用mkfs 指令格式化设备时,块大小作为文件系统选项的一部分为被指定,指定块大小的参数随文件系统的变化。
4 几何
文件系统的几何与文件系统中数据的分布有关,如果系统使用带状存储器,如RAID,可以格式化设备时,通过重新排列数据和底层存储几何的元数据提高性能。
很多数据导出的推荐几何在使用特定文件系统格式化设备时会被自动设置。如果设备没有导出这些推荐几何,或您想要变更推荐设置,那么您在使用 mkfs 格式化设备时,需要手动指定几何 。
5 外部日记
日志文件系统会在执行写操作之前,将写操作期间发生的变化记录到日志文件中,这会降低系统发生故障,电源故障时日志的存储设备损坏的可能性,并加速恢复过程
元数据密集工作负载设计日志的频繁更新,大型日志使用更多内存,但会较少操作的频繁性,此外,可通过将设备日志置于和主要存储一样快或者更快的专用存储上,提高带有元数据密集型工作负载的设备的寻道时间。
确保外部日志的可靠性,失去外部日志,设备将导致文件系统的损坏
外部日志必须在格式化时创建,并在挂载期间制定日志设备
6 挂载事件注意事项
1 barrier(屏蔽)
文件系统的barrier确保文件系统元数据正确写入到永久存储并排序,使用fsync传输数据在断电下得以存留,以前的redhat版本中,启用文件系统barrier会明显放慢严重依赖fsync的应用程序,或者创建和删除很多小文件
红帽企业版Linux 7 中,文件系统barrier性能的得到改善是使禁用的文件系统barrier的性能影响变的极小(小于3%)
2 访问时间
每次读取文件,它的元数据随着访问时间atime更新,这涉及额外的I/O,在大多数情况下,这项的开销是小的,因为在默认情况下,前一次访问时间早于上一次修改时间(mtime)或者状态变化(ctime),redhat 7 只会更新atime。
然而,如果更新元数据耗时,且并不对准确访问时间做要求,其可以使用noatime挂载选项挂载文件系统,读取文件时会禁用元数据的更新,它也会启用nodiratime行为,读取目录时,该行为禁用元数据的更新
3 预读
预读行为通过预取可能立即需要的数据,并将其加载到可比磁盘上更快检索的页面缓存中加速文件系统访问,预读值越高,系统预取数据越早。
redhat 企业版Linux 根据对文件系统的检查,尝试设置一个合适的预读值,然后检查不可能总是准确的,涉及大量数据流的量数据流的顺序I/O的工作负载常常受益于高预读值,redhat 企业版 Linux 7 提供的相关存储调整配置文件提高预读值,和使用 LVM 条带化一样,但这些调整对于所有工作负载而言并不总是足够的。
7 维护
定期丢弃文件系统中不可用的块是对于固态硬盘和精简装置粗出的建议做法,有两种丢弃不使用的块的做法:
batch discard(批量和丢弃)
这种丢弃方式是fstrim指令的一部分,它丢弃文件系统中和管理员指定的标准相匹配的所有不适用的块
redhat Linux 7 支持 XFS 和 ext4 格式化设备上的 batch discard,这些设备支持实际丢弃操
作即( /sys/block/devname/queue/discard_max_bytes 值不为 0 的 HDD 设备,和/sys/block/sda/queue/discard_granularity 不为 0 的 SSD 设备)。
online discard(网络丢弃)
这种方式的丢弃操作在挂载时是discard选项配置。实际运行不受用户干扰,然而,online discard 只丢弃从使用转换到空闲的块,Redhat 7 支持 XFS 和 Ext4格式化设备上的online discard红帽推荐 batch discard,除非要求用 online discard 维持性能,或 batch discard 不可用于系统工作负载。
预先分配
预先分配将硬盘空间标记为已经跟将磁盘空间分配给一个文件,为未将数据写入该空间,这可用于限制数据碎片和较差的读取性能,Redhat Linux 7 支持挂载事件内XFS,Ext4和GFS2 设备上预先分配空间/
6 使用system tap 监控存储
下列的 SystemTap 示例脚本与存储性能有关,并可能有助于诊断存储或文件系统性能问题。默认设置下,
安装它们至 /usr/share/doc/systemtap-client/examples/io 目录下。
disktop.stp
每 5 秒检查读/写硬盘状态并输出在此期间的前十项。
iotime.stp
显示用在读操作和写操作的时间量,以及读和写的字节量。
traceio.stp
根据观察到的累计 I/O 流,显示每秒前十项可执行文件。
traceio2.stp
在特定设备进行读和写操作时,显示可执行的名称和进程标识符。
inodewatch.stp
每当在特定主要/次要设备上的特定 inode 上进行读或者写操作时,显示可执行的名称和进程标识符。
inodewatch3.stp
每当在特定主要/次要设备上的特定 inode 上属性发生变化时,显示将可执行的名称、进程标识符、和属性。
6 配置工具
1 配置存储性能的调整配置文件
tuned 和 tuned-adm 提供一些旨在为特定用例提高性能的配置意见,下面配置文件有利于提高存储性能尤为重要
其作用有
1 延迟性能
2 吞吐量性能
如需配置文件系统中的配置文件,请运行下面命令,用您想用的配置文件名称替代 name。
$ tuned-adm profile name
tuned-adm recommend 命令为系统推荐合适的配置文件,在安装时它也会为系统设置默认配置文件,因此可用于返回默认配置文件
2 设置默认I/O调度器
如果设备的挂载选项没有指定调度器,可使用默认的I/O调度器
如需设置默认I/O调度器,在重启时通过向内核命令行附加elevator参数来指定想要使用的调度器,或通过编辑/etc/grub2.conf文件
elevator=scheduler_name
3 为设备配置I/O调度器
如需设置特定存储设备的调度器或者调度器的优先级顺序,编辑/sys/block/devname/queue/scheduler 文件,devname 为你预配置的设备的名称
[root@python ~]# cat /sys/block/sda/queue/scheduler
noop [deadline] cfq
[root@python ~]# echo cfq > /sys/block/sda/queue/scheduler
[root@python ~]# cat /sys/block/sda/queue/scheduler
noop deadline [cfq]
[root@python ~]#
4 调整deadline调度器
使用deadline时,排队的I/O请求将分为读批处理和写批处理,然后按照LBA递增的执行顺序调度,默认设置下,读批处理优先于写批处理,这是因为在读I/O上引用程序易被阻止,在批处理被处理后,deadline 会检查写操作因等待处理器时间而处于多久的"饥饿"状态,并合理调度下一个读或者写批处理。
下面参数形象deadline调度器行为
fifo_batch
单个批处理中读操作或者写操作发出的数量,默认为16,值越高,吞吐量也会更多,但也会增加延迟
front_merges
如果您的工作负载从不产生正面合并,可调整的参数设置为0,然而,除非你已经测试了该检查的开销,推荐1为默认值
read_expire
应为服务调度读请求中毫秒的数量,默认值为500(0.5秒)
write_expire
应为服务器调度写请求中的毫秒数量,默认值为5000(5秒)
writes_started
先于写批处理而处理的读批处理数量,该值越高,给读批处理的优先更多
5 调整cfg 调度器
使用cfg时,进程分为三类,实时,尽其所能和空间,尽其所能进程之间调度所有实时进程,而空间进行之前调度尽其所能进程,默认情况下,进程归类为尽其所能,可使用ionice 命令手动调整进程分类
通过使用下面参数进一步调整cfg调度器的行为,这些参数通过改变/sys/blog/devname/queue/iosched 目录下的指定文件,基于每个设备设置的
[root@python iosched]# ll
总用量 0
-rw-r--r-- 1 root root 4096 12月 10 23:01 back_seek_max
-rw-r--r-- 1 root root 4096 12月 10 23:01 back_seek_penalty
-rw-r--r-- 1 root root 4096 12月 10 23:01 fifo_expire_async
-rw-r--r-- 1 root root 4096 12月 10 23:01 fifo_expire_sync
-rw-r--r-- 1 root root 4096 12月 10 23:01 group_idle
-rw-r--r-- 1 root root 4096 12月 10 23:01 low_latency
-rw-r--r-- 1 root root 4096 12月 10 23:01 quantum
-rw-r--r-- 1 root root 4096 12月 10 23:01 slice_async
-rw-r--r-- 1 root root 4096 12月 10 23:01 slice_async_rq
-rw-r--r-- 1 root root 4096 12月 10 23:01 slice_idle
-rw-r--r-- 1 root root 4096 12月 10 23:01 slice_sync
-rw-r--r-- 1 root root 4096 12月 10 23:01 target_latency
[root@python iosched]# pwd
/sys/block/sda/queue/iosched
back_seek_max
cfq 将执行向后搜寻千字节计算的最大距离,默认是16kb,向后搜寻通常会损害性能,因此不推荐使用大的值
back_seek_penalty
磁头在决定向前还是向后移动时,乘法器应用于向后搜寻,默认值为2,如果磁头位置是1024kb,并且系统中有等距的请求,back_seek_penalty
应用于向后搜寻距离和磁盘向前移动。
fifo_expire_async
异步(缓冲写入)请求以毫秒计算可能持续无服务的时间长度,在这个时间过期之后,一个单独的饥饿的异步请求移动至配送列表,默认值为250毫秒。
fifo_expire_sync
同步(读取或者O_DIRECT 写入)请求以毫秒计算的可能持续无服务的时间长度,在这个时期过期后,一个单独的"饥饿"的同步请求被移动至配送列表,默认值为125毫秒。
group_idle
默认情况下,此参数设置为0,表示禁用,设置为1(启用)时,cfg 调度器空闲在控制组中发出I//O的最后进程里,如使用成比例的重量 I/O 控制组,或 slice_idle 设置为 0 (在快速存储上)会有帮助。
group_isolation
默认设置下,该参数设置为 0(禁用)。设置为 1(启用)时,它提供组之间更强的隔离,但是吞吐量会减少,这是因为公平性用于随机和顺序工作负载。group_isolation 禁用时(设置为0),公平性只提供给顺序工作负载。
low_latency
默认设置下,设置参数为1(启用),启用后。通过为设备上发出I/O的每个进程提供最大为300ms的等待时间,CFG 更注重公平性而非吞吐量,设置参数为0时(禁用),目标延迟被忽略,每个进程接受完成的时间片
quantum
该参数定义cfg在同一时间发给一个设备的I/O请求的数量,实际上是对队列深度的限制,默认值为8个请求,使用的设备可能支持更大的队列深度,但增加队列深度会导致延迟,尤其是大的顺序写工作负载
slice_async
该参数定义分配给每个发出异步I/O请求的进程的时间片长度,默认为40毫秒
slice_idle
该参数指定等待下一步请求时以毫秒计算的cfg空间时间长度,默认为0(队列无空间或者 service tree level).默认值对于外部raid 存储器的推图量是理想的,由于增加了搜寻操作的整体数量,从而降低呢哦不non-RAID 存储器的吞吐量
slice_sync
该参数定义分配给每个发出异步I/O请求的进程的时间片长度,默认值为100ms
为快速存储调整 cfg
不像无法遭受大搜寻 penalty(惩罚)的硬件推荐 cfq 调度器,例如快速外部存储数列或者固态硬盘。如果
您需要在此存储上使用 cfq ,需要编辑下列配置文件:
设置 /sys/block/devname/queue/ionice/slice_idle为0
设置 /sys/block/devname/queue/ionice/quantum 为64
设置 /sys/block/devname/queue/ionice/group_idle为 1
6 调整noop 调度器
noop I/O 调度器主要对使用快速存储的受CPU限制有用,请求在块层合并,因此通过编辑/sys/block/sdx/queue/ 目录中的文件中块层参数,修改noop 行为
[root@python ~]# echo noop > /sys/block/sda/queue/scheduler
[root@python ~]# cat /sys/block/sda/queue/scheduler
[noop] deadline cfq
[root@python ~]# cd /sys/block/sda/queue/iosched/
[root@python iosched]# ll
总用量 0
[root@python iosched]# cd ..
[root@python queue]# pwd
/sys/block/sda/queue
[root@python queue]# ll
总用量 0
-rw-r--r-- 1 root root 4096 12月 10 23:01 add_random
-r--r--r-- 1 root root 4096 12月 10 23:01 discard_granularity
-r--r--r-- 1 root root 4096 12月 10 23:01 discard_max_bytes
-r--r--r-- 1 root root 4096 12月 10 23:01 discard_zeroes_data
-r--r--r-- 1 root root 4096 12月 10 23:01 hw_sector_size
drwxr-xr-x 2 root root 0 12月 10 23:27 iosched
-rw-r--r-- 1 root root 4096 12月 10 23:01 iostats
-r--r--r-- 1 root root 4096 12月 10 23:01 logical_block_size
-r--r--r-- 1 root root 4096 12月 10 23:01 max_hw_sectors_kb
-r--r--r-- 1 root root 4096 12月 10 23:01 max_integrity_segments
-rw-r--r-- 1 root root 4096 12月 10 23:01 max_sectors_kb
-r--r--r-- 1 root root 4096 12月 10 23:01 max_segments
-r--r--r-- 1 root root 4096 12月 10 23:01 max_segment_size
-r--r--r-- 1 root root 4096 12月 10 23:01 minimum_io_size
-rw-r--r-- 1 root root 4096 12月 10 23:01 nomerges
-rw-r--r-- 1 root root 4096 12月 10 23:01 nr_requests
-r--r--r-- 1 root root 4096 12月 10 23:01 optimal_io_size
-r--r--r-- 1 root root 4096 12月 10 23:01 physical_block_size
-rw-r--r-- 1 root root 4096 12月 3 21:14 read_ahead_kb
-rw-r--r-- 1 root root 4096 12月 10 23:01 rotational
-rw-r--r-- 1 root root 4096 12月 10 23:01 rq_affinity
-rw-r--r-- 1 root root 4096 12月 10 23:27 scheduler
-rw-r--r-- 1 root root 4096 12月 10 23:01 unpriv_sgio
-r--r--r-- 1 root root 4096 12月 10 23:01 write_same_max_bytes
add_random
一些I/O时间会影响 /dev/random的熵池,如果这些影响的负荷变得可测量,该参数可设置为0
max_sectors_kb
指定I//O请求的最大尺寸(以千字节计算),默认值为512kb,该参数的最小值是由存储设备的逻辑块大小决定的,该参数的最大值是由max_hw_sectors_kb值决定的。
I/O请求大于内部存储块大小时,一些固态硬盘会表现不佳,这种情况下,redhat推荐将max_hw_sectors_k减少至内部存储块大小
nomerges
大多数工作负载受益于请求合并,然而,禁用合并有助于调试目的,可设置参数为0禁用合并,默认设置下为启用(设置为1)。
nr_requests
限定同一时间排队的读和写请求的最大数量。默认值为 128, 即在请求读或者写操作的下一个进程进入睡眠模式前有 128 个读请求和 128 个写请求排队。对于延迟敏感应用程序,降低该参数值,并限制存储上的命令队列深度,这样回写 I/O 便无法填充有写请求的设备队列。设备队列填充时,其他尝试执行 I/O 操作的进程会进入睡眠模式,直到有可用队列空间。随后请求会以 round-robin fashion(循环方式)分配,以防止一个进程持续使用队列所有点。
optimal_io_siz e
一些存储设备用此参数报告最佳 I/O 大小。如果报告该值,红帽建议您尽可能将应用程序发出 I/O与最佳 I/O 大小对齐,并是最佳 I/O 大小的倍数。
read_ahead_kb
定义操作系统在顺序读取操作阶段将预先读取的千字节数量,以便存储在页面缓存中可能马上需要的信息。设备映射程序经常受益于高read_ahead_kb 值 128 KB ;对于访问将要被映射的设备这是一个良好起点。
旋转
一些固态硬盘不能正确公布其固态硬盘状态,并且会如传统旋转磁盘载。如果您的固态硬盘不能将它自动设置它为 0,那么请您手动设置,禁用调度器上不必要的搜寻减少逻辑。
rq_affinity
默认设置下,I/O 完成能在不同处理器上进行,而不是限定在发出 I/O 请求的处理器上。将rq_affinity 设置为 1 以禁用此能力,并只在发出 I/O 请求的处理器上执行完成。这能提高处理器数据缓存的有效性
7 为性能配置文件系统
如果文件碎片或者资源争用引起性能损失,性能通常可通过重新配置文件系统而提高性能。然而,在有些用例中,可能需要更改应用程序。
1 调整XFS
XFS 默认格式化和挂载设置适用于大多数工作负载。红帽建议只在更改特定配置会对您的工作负载有益时对它们进行更改。
1 格式化选项参数
目录块大小
目录块大小影响每个 I/O 操可检索或修改的目录信息数量。目录块大小最小值即文件系统块大小、(默认设置下为4 KB)。目录块大小最大值为 64 KB。
对于指定的目录块大小来说,大的目录比小的目录需要更多 I/O。因为和小目录块的系统相比,大目录块大小的系统每 I/O 操作会使用更多的处理能力。因此,根据您的工作负载,推荐使用尽可能小的目录和目录块大小。
如文件系统比大量写和大量读工作负载的列出项目数量少,红帽推荐使用以下目录块大小,请见如下
〈表 5.1 “为目录块大小推荐的最大目录项” 〉
目录块大小 最大项 (大量读操作) 最大项 (大量写操作)
4 KB 100000–200000 1000000–2000000
16 KB 100000–1000000 1000000–10000000
64 KB > 1000000 >10000000
在不同大小文件系统中,目录块大小对读和写工作负载的影响的情况请参见 XFS 文件。
分配组
分配组是独立的结构,指示自由空间并在文件系统中一节分配 inodes。只要同时操作影响不同分配组,每个分配组能被独立修改,这样 XFS 同时执行分配和解除分配操作。因此文件系统中执行的同时操作数量和分配组数量相等。然而,由于执行同时操作的能力受到能够执行操作的处理器数量的限制,红帽建议分配组数量应多于或者等于系统中处理器的数量。
多个分配组无法同时修改单独目录。因此,红帽推荐大量创建和移除文件的应用程序不要在单个目录中存储所有文件。
增长约束
如果在格式化之后,需要增加文件系统的大小,由于分配组大小在完成格式化之后不能更改,需要考虑布局必须根据文件系统的最终能力,而非根据初始化能力调节分配组大小,占据所有使用空间的文件系统中分配组数量不应超过数百,除非分配组处于最大尺寸(1TB),因此,红帽想大部分文件系统推荐最大增长,允许文件系统是初始大小的十倍。
增长RAID数组的文件系统时,务必考虑额外护理,由于设备大小必须与固定多个分配组大小对齐,以便新分配组表头在新增加的存储中正确对齐,由于几何在格式化之后不能被修改,因此新存储也必须与已有存储几何一致,因此,在同一块设备上,不能优化不同几何的存储。
iNode 大小和内联属性
如果iNode有足够可用空间,XFS能直接将属性名称和值写入inode,由于不需要额外的I/O,这些内联属性能够被获取和修改,达到比获取单独的属性块更快的量级。
默认 inode 大小为 256 bytes。其中只有约 100 bytes 大小可用于属性存储,取决于 inode 上存储的数据范围指针数量。格式化文件系统时,增加 inode 大小能增加存储属性可用的空间数量。
属性名称和属性值两者都受到最大尺寸 254 bytes 的限制。如果名称或者值超过 254 bytes 长度,该属性会被推送到单独的属性快,而非存储在内联中。
RAID
如果使用软件 RAID ,mkfs.xfs 会使用合适的带状单元和宽度自动配置底层的硬件。然而,如果使用硬件 RAID, 带状单元和宽度可能需要手动配置,这是因为不是所有硬件 RAID 设备输出此信息。使用 mkfs.xfs -d 选项配置带状单元和宽度。更多信息请参见 mkfs.xfs 手册页。
日志大小
直到同步事件被触发,待定的更改在内存中累计,这个时候它们会被写入日志。日志大小决定同时于进行中的修改数量。它也决定在内存中能够累计的最大更改数量,因此决定记录的数据写入磁盘的频率。与大日志相比,小日志促使数据更频繁地回写入磁盘。然而,大日志使用更多内存来记录待定的修改,因此有限定内存的系统将不会从大日志获益。
日志与底层带状单元对齐时,日志表现更佳;换言之,它们起止于带状单元边界。使用 mkfs.xfs -d 选项将日志对齐带状单元,更多信息请参见 mkfs.xfs 手册页。
使用下列 mkfs.xfs 选项配置日志大小,用日志大小替换 logsize :
# mkfs.xfs -l size=logsize
更多详细信息参见 mkfs.xfs 手册页:
$ man mkfs.xfs
日志带状单元
日志写操作起止于带状边界时(与底层带状单元对齐),存储设备上使用 RAID5 或 RAID6 布局的日志写操作可能会表现更佳。mkfs.xfs 尝试自动设置合适的日志带状单元,但这取决于输出该信息的 RAID 设备。如果您的工作负载过于频繁地触发同步事件,设置大日志带状单元会降低性能。这是因为小的写操作需要填充至日志带状单元,而这会增加延迟。如果您的工作负载受到日志写操作延迟的约束,红帽推荐将日志带状单元设置为 1 个块,从而尽可能地触发非对齐日志写操作。支持的最大日志带状单元为最大日志缓存的大小(256 KB)。因此底层存储器可能拥更大的带状单元,且该带状单元能在日志中配置。在这种情况下,mkfs.xfs 会发出警告,并设置一个大小为32 KB 的日志带状单元。使用以下选项之一配置日志带状单元,其中 N 是被用于带状单元的块的数量,size 是以 KB 为单位的带状单元的大小。
mkfs.xfs -l sunit=Nb
mkfs.xfs -l su=size
更多详细信息参见 mkfs.xfs 手册页:
$ man mkfs.xfs
2 挂载选项
iNode 分配
建议文件系统大于1TB,iNode64参数配置XFS,从而在文件系统中分配iNode和数据,这样能保证iNode不会被大量分配到文件系统的起始位置,数据也不会被大量分配到文件系统的结束位置,从而提高大文件系统的性能表现。
日志缓存和数量
日志缓存越大,将所有变更写入日志的I/O操作越少,大日志缓存能提高有大量I/O密集型总负载的系统表现,该工作负载没有非易变的写缓存。
通过 logbsize 挂载选项配置日志缓存大小,并确定日志缓存中信息存储的最大数量。如果未设置日志带状单元,缓存写操作可小于最大值,因此不需要减少大量同步工作负载中的日志缓存大小。
默认的日志缓存大小为 32 KB。最大值为 256 KB, 也支持 64 KB、128 KB 或以 2 的倍数为幂的介于 32 KB 和 256 KB 之间的日志带状单元。
日志缓存的数量是由 logbufs 挂载选项确定的。日志缓存的默认值为 8 (最大值),但能配置的日志缓存最小值为2。通常不需要减少日志缓存的数量,除非内存受限的系统不能为额外的日志缓存分配内存。减少日志缓存的数量会降低日志的性能,尤其在工作负载对 I/O 延迟敏感的时候。
延延迟变更日志
内存的变更写入日志前,XFS 的选项能集成这些改变。 delaylog 参数允许将频繁更改的元数据周期性地写入日志,而非每次改变都要记录到日志中。此选项会增加故障中操作丢失的潜在数量,也会增加用于跟踪元数据的内存大小。但是,它能通过按量级排序增加元数据的更改速度和可扩展性,为确保数据和元数据写入硬盘而使用 fsync、fdatasync 或sync 时,此选项不能减少数据或元数据的完整性。
2 调整 ext4
1 格式化选项
iNode 表初始化
在很大的文件系统上初始化文件系统中的所有iNode会耗时很久,默认设置下回推迟初始化过程(启用迟缓iNode表初始化),但是,如果没ext4驱动,默认设置下回禁用迟缓iNode表初始化,可通过设置lazy_itable_init为1启用,那么在挂载后,内核进程继续初始化文件系统
2 挂载选项
inode 表初始化率
启用迟缓 inode 表初始化时,您可通过指定 init_itable 参数值控制初始化发生的速率。执行后台初始化的时间约等于 1 除以该参数值。默认值为 10。
自自动文件同步
对现有文件重命名、截断或重写后,一些应用程序无法正确执行 fsync。默认设置下,执行这些操作之后,ext4 会自动同步文件。但这样会比较耗时。
如果不需要此级别的同步,您可在挂载时通过指定 noauto_da_alloc 选项禁用该行为。如果noauto_da_alloc 已设置,应用程序必须明确使用 fsync 以确保数据的持久化。
日志 I/O 优先级
默认设置下日志 I/O 优先级为 3,该值比常规 I/O 的优先级略高。您可在挂载时使用
journal_ioprio 参数控制日志 I/O 的优先级。journal_ioprio 的有效值范围为从 0 到 7,
其中 0 表示具有最高优先级的 I/O。
3 调整 btrfs
自红帽企业版 Linux 7.0 起,btrfs 作为技术预览而为用户提供。如果 btrfs 受到全面支持,本章节将在未来更新。
调整 GFS2
本章节涵盖 GFS2 文件系统在格式化和挂载时可用的调整参数。
目目录间距GFS2 挂载点的顶层目录中创建的所有目录都是自动间隔,以减少目录中的碎片并提高写速度。为像顶层目录间隔其他目录,用 T 属性标注该目录,如示,用您想间隔该目录的路径替代 dirname。
# chattr +T dirname
chattr 作为 e2fsprogs 软件包中的一部份为用户提供。
减减少争用GFS2 使用全域锁机制,该机制需要簇中节点之间的通信。多节点之间的文件和目录争用会降低性能。通过最小化多节点间共享的文件系统区域,您可将缓存失效的风险最小化.
4 网络
网络子系统由很多敏感连接的不同部分构成。红帽企业版 Linux 7 网络因此旨在为大多数工作负载提供最佳性能,并且自动优化其性能。因此,不需要时常手动调节网络性能。本章探讨了可以对功能网络系统做的进一步优化。
1 注意事项
若需要调优,用户需要对redhat 企业版Linux网络包的接受有充分认识,
2 基本原理
1 网络收包处理基本原理
发送至redhatLinux 系统的数据包是由 NIC(网络接口卡)接受的,数据包置于内核硬件缓冲或者是循环缓冲区中,NIC之后会发送一个硬件终端请求,促使生成一个软件中断操作来处理该中断请求,作为软件中断操作的一部分,数据包会由缓冲区转移到网络堆栈,根据数据包及用户的网络配置,数据包之后会被转发,删除或者转移到一个应用程序的socket接受队列,并将从网络堆栈中删除,这一进程会持续进行,直到NIC硬件缓冲区中没有数据包或者一定数量的数据包(在 /proc/sys/net/core/dev_weight 中指定)被转移。
2 网络性能影响因素
网络性能问题最常见的是由硬件故障或者基础结构层故障造成的
数据包接受瓶颈
虽然网络堆栈基本上是自我优化的,但是在网络堆栈处理过程中后很多呆滞瓶颈且降低性能的问题
NIC 硬件缓冲区或循环缓冲区
如果大量数据包被弃置,硬件缓冲区就会成为瓶颈,要监控系统传动的数据包,需要使用ethool硬件或软件中断队列
中断会增加延迟,争用处理器。
应用程序的socket接收队列
应用是程序接收队列的瓶颈是大量的数据包没有复制到请求的应用程序中,或者是UDP输入错误增加,此错误在/proc/net/snmp中。
3 监控和诊断性能问题
1 ss
ss 是一个命令行实用程序,显示关于 socket的数据信息,允许管理员随时评估设备性能。ss 列表会默认打开没有注意到但已建立了连接的 TCP socket,但是会提供大量有用的选项来给管理员筛选特定的 socket数据。
红帽推荐在红帽企业版 Linux 7 中使用 ss 来替代 netstat。
2 ip
ip 实用程序允许管理员管理和监控线路、设备、路由策略及通道。ip monitor 指令可以持续监控设备、地址和线路的状况。
3 dropwatch
Dropwatch 是一个交互工具,用来监控和记录内核弃置的数据包。
4 ethtool
ethtool 实用程序允许管理员查看和编辑网络接口卡的设置。它有助于观察特定设备的数据,例如该设备弃
置的数据包数量。
用户可以使用 ethtool -S 查看特定设备的计数状态和想要监控的设备名称。
ethtool -S devname
5 /proc/net/snmp
/proc/net/snmp 文件显示的数据是snmp用来监控和管理IP,ICMP,TCP和UDP的,定期检查此文件可以协助管理员识别异常值,从而识别潜在的性能问题,如 UDP输入错误(InErrors)增加,且错误在/proc/net/snmp中,就意味着socket接收队列中出现了瓶颈。
[root@centos8 ~]# cat /proc/net/snmp
Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates
Ip: 1 64 837779 0 0 0 0 0 837749 711025 0 2 0 60 30 0 0 0 0
Icmp: InMsgs InErrors InCsumErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
Icmp: 28091 13028 0 28088 0 0 0 0 3 0 0 0 0 0 28125 0 28122 0 0 0 0 0 3 0 0 0 0
IcmpMsg: InType3 InType8 OutType0 OutType3
IcmpMsg: 28088 3 3 28122
Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts InCsumErrors
Tcp: 1 200 120000 -1 15481 26 14418 25 4 793658 977256 12557 1 94 0
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti
Udp: 7245 34 0 884 0 0 0 8577
UdpLite: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti
UdpLite: 0 0 0 0 0 0 0 0
4 配置工具
1 网络性能tuned-adm配置文件
tuned-adm 对很多特定用例提供不同配置文件以提高性能
延迟性能
网络延迟
网络吞吐量
2 配置硬件缓冲区
如果硬件缓冲区弃置了大量的数据包,那么有很多可能的解决方法。
减缓输入流量
筛选传入的流量,减少加入的多播组数量或减少广播流量,以降低队列填充率。
调整硬件缓冲队列
通过增加队列的大小以减少传动的数据包数量,使其不易过剩,用户可以使用ethtool 指令来更改网络设备的rx/tx参数
ethtool --set-ring devname value
改变队列的排除率
设备重量是指设备一次可以接收的数据包数量(单个预定处理器访问)。用户可以通过提高设备重量以增加队列的排出比率,这由dev_weight 参数控制。此参数可以通过变/proc/sys/net/core/dev_weight 文件的内容来做临时更改,或使用 sysctl 进行永久更改,这由 procps-ng 数据包提供。
改变队列排出率通常是缓解不良网络性能最简单的方法。但是,增加设备一次可以接收的数据包数量会消耗处理器额外的时间,在此期间不可调度其他进程,因此可能会导致其他性能问题。
3 配置中断队列
如果分析显示高延迟,系统可能受益于基于轮询的包接收,而不是基于中断的包接收。
1 配置繁忙轮训
繁忙轮询有助于减少网络接收路径中的延迟, 使 socket 层代码查询网络设备的接收队列并禁用网络中断,这可以消除由于中断和由此产生的环境切换所造成的延误。但是,它会增加 CPU 的使用率。繁忙轮询可以防止CPU 进入睡眠状态,睡眠状态会造成额外的功耗。
繁忙轮询是默认禁用的。要在特定 socket 中启用繁忙轮询,请按以下指示:
将 sysctl.net.core.busy_poll 设置为除 0 以外的值。这一参数控制的是 socket 轮询和选择位于等待设备队列中数据包的微秒数。红帽推荐值为 50。
添加 SO_BUSY_POLL socket 选项至 socket。
要全局启用繁忙轮询, 须将 sysctl.net.core.busy_read 设置为除了 0 以外的值。这一参数控制了socket 读取位于等待设备队列中数据包的微秒数,且设置了 SO_BUSY_POLL 选项的默认值。红帽推荐在socket 数量少时将值设置为 50 , socket 数量多时将值设置为 100。对于 socket 数量极大时(超过几百),请使用 epoll。
繁忙轮询由以下驱动程序支持。红帽企业版 Linux 7 支持这些驱动程序。
bnx2x
be2net
ixgbe
mlx4
myri10ge
4 配置socket接收队列
如果分析数据显示,数据包由于 socket 队列排出率太慢而被弃置,有几种方法来解决由此产生的性能问题。
减少传入流量的速度
减少队列填充速率可以通过筛选或弃置进入队列前的数据包,或是减少设备重量。
设备重量是指设备一次可以接收的数据包数量,设备重量由dev_weight参数控制,此参数可以通过改变/proc/sys/net/core/dev_weight 文件的内容来做临时更改,或者是使用sysctl 来做永久更改
[root@centos8 ~]# cat /proc/sys/net/core/dev_weight
64
增加队列深度
增加应用程序的 socket 队列深度往往是提高 socket 队列排出率最简单的方法,但不可能是一个长期的解决方法。
要增加队列深度就要增加 socket 接收缓冲区的大小,可以做如下变化:
增加 /proc/sys/net/core/rmem_default 值
这一参数控制 socket 使用的接收缓冲区的默认大小,这个值必须小于
/proc/sys/net/core/rmem_max 的值。
使用 setsockopt 配置较大的 SO_RCVBUF 值
这一参数控制的是以字节为单位的 socket 接收缓冲区的最大值。使用 getsockopt 系统调用来确
定当前缓冲区的值。
5 配置 RSS
RSS(接收端调整),也叫做多队列接受,是通过一些基于硬件的接受队列来分配网络接受进程,从而使得入站网络流量可以由多个CPU进行处理,RSS可以用来缓解接受中断进程中由单个CPU过载而出现的瓶颈,并减少网络延迟。
要确定您的网络接口卡是否支持 RSS,须查看多个中断请求队列是否在 /proc/interrupts 中有相关的接口。例如,如果用户对 p1p1 接口有兴趣:
# egrep 'CPU|p1p1' /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5
89: 40187 0 0 0 0 0 IR-PCI-MSI-edge
p1p1-0
90: 0 790 0 0 0 0 IR-PCI-MSI-edge
p1p1-1
91: 0 0 959 0 0 0 IR-PCI-MSI-edge
p1p1-2
92: 0 0 0 3310 0 0 IR-PCI-MSI-edge
p1p1-3
93: 0 0 0 0 622 0 IR-PCI-MSI-edge
p1p1-4
94: 0 0 0 0 0 2475 IR-PCI-MSI-edge
p1p1-5前的输出显示 NIC 驱动程序为 p1p1 接口创建了 6 个接收队列(p1p1-0 至 p1p1-5)。也显示出每个队列处理的中断数量以及处理中断的 CPU。在这种情况下,由于有 6 个默认队列,这一特殊的 NIC 驱动程序就为每个 CPU 创建一个队列,这个系统一共有 6 个 CPU。这是 NIC 驱动程序中很常见的模式。或者用户可以在网络驱动程序加载后查看 ls -1/sys/devices///device_pci_address/msi_irqs 的输出。
例如,如果用户对 PCI 地址为0000:01:00.0 的设备感兴趣,可以通过以下指令来列出该设备中断请求队列:
ls -1 /sys/devices///0000:01:00.0/msi_irqs
101
102
103
104
105
106
107
108
109
RSS 是默认启用的。RSS 的队列数(或是需要运行网络活动的 CPU )会由适当的网络驱动程序来进行配置。 bnx2x 驱动程序是在 num_queues 中进行配置。sfc 驱动程序是用 rss_cpus 参数进行配置。通常,这都是在 /sys/class/net/device/queues/rx-queue/ 中进行配置,其中 device 是网络设备的名称(比如 eth2),rx-queue 是适当的接收队列名称。
配置 RSS 时,红帽推荐限制每一个物理 CPU 内核的队列数量。超线程在分析工具中通常代表独立的内核,但是所有内核的配置队列,包括如超线程这样的逻辑内核尚未被证实对网络性能有益。
启用时,基于每个队列的 CPU 进程数量,RSS 在 CPU 间平等地分配网络进程。但是,用户可以使用
ethtool –show-rxfh-indir 和 –set-rxfh-indir 参数来更改网络活动的分配方式,并权衡哪种类型的网络活动更为重要。
irqbalance 后台程序可与 RSS 相结合,以减少跨节点内存及高速缓存行反弹的可能性。这降低了处理网络数据包的延迟。
6 配置 RPS
RPS(接收端包控制)与 RSS类似,用于将数据包指派至特定的 CPU 进行处理。但是,RPS 是在软件级别上执行的,这有助于防止单个网络接口卡的软件队列成为网络流量中的瓶颈。
较之于基于硬件的 RSS ,RPS 有几个优点:
RPS 可以用于任何网络接口卡。
易于添加软件过滤器至 RPS 来处理新的协议。
RPS 不会增加网络设备的硬件中断率。但是会引起内处理器间的中断。
每个网络设备和接收队列都要配置 RPS,在/sys/class/net/device/queues/rxqueue/rps_cpus 文件中,device 是网络设备的名称(比如 eth0),rx-queue 是适当的接收队列名称(例如 rx-0)。
rps_cpus 文件的默认值为 0。这会禁用 RPS,以便处理网络中断的 CPU 也能处理数据包。
要启用 RPS,配置适当的 rps_cpus 文件以及特定网络设备和接收队列中须处理数据包的 CPU 。
rps_cpus 文件使用以逗号隔开的 CPU 位图。因此,要让 CPU 在一个接口为接收队列处理中断,请将它们在位图里的位置值设为 1。例如,用 CPU 0、1、2 和 3 处理中断,将 rps_cpus 的值设为 00001111
(1+2+4+8),或 f(十六进制的值为 15)。
对于单一传输队列的网络设备,配置 RPS 以在同一内存区使用 CPU 可获得最佳性能。在非 NUMA 的系统中,这意味着可以使用所有空闲的 CPU。如果网络中断率极高,排除处理网络中断的 CPU 也可以提高性能。
对于多队列的网络设备,配置 RPS 和 RSS 通常都不会有好处,因为 RSS 配置是默认将 CPU 映射至每个接收队列。但是,如果硬件队列比 CPU 少,RPS依然有用,并且配置 RPS 是来在同一内存区使用 CPU。
7 配置 RFS
RFS(接收端流控制) 扩展了RPS 的性能以增加CPU缓存命中率,以此减少网络延迟,RPS仅基于队列长度RFS 使用 RPS 后端预测最合适的 CPU,之后会根据应用程序处理数据的位置来转发数据包。这增加了 CPU 的缓存效率。
RFS 是默认禁用的。要启用 RFS,用户须编辑两个文件:
/proc/sys/net/core/rps_sock_flow_entries
设置此文件至同时活跃连接数的最大预期值。对于中等服务器负载,推荐值为 32768 。所有输入的值四舍五入至最接近的2的幂。/sys/class/net/device/queues/rx-queue/rps_flow_cnt
将 device 改为想要配置的网络设备名称(例如,eth0),将 rx-queue 改为想要配置的接收队列名称(例如,rx-0)。
将此文件的值设为 rps_sock_flow_entries 除以 N,其中 N
是设备中接收队列的数量。例如,如果 rps_flow_entries 设为 32768,并且有 16 个配置接收队列,那么rps_flow_cnt 就应设为 2048。对于单一队列的设备,rps_flow_cnt 的值和rps_sock_flow_entries 的值是一样的。
从单个发送程序接收的数据不会发送至多个 CPU。如果从单个发送程序接收的数据多过单个 CPU 可以处理的数量,须配置更大的帧数以减少中断数量,并以此减少 CPU 的处理工作量。或是考虑 NIC 卸载选项来获得更快的 CPU。
考虑使用 numactl 或 taskset 与 RFS 相结合,以将应用程序固定至特定的内核、 socket 或 NUMA 节点。这可以有助于防止数据处理紊乱。
8 配置加速 RFS
加速 RFS 是通过添加硬件协助来增速的。如同 RFS,数据转发是基于应用程序处理数据包的位置。但不同于传统 RFS 的是,数据是直接发送至处理数据线程的本地 CPU:即运行应用程序的 CPU,或是对于在缓存层次结构中的 CPU 来说的一个本地 CPU。
加速 RFS 只有满足以下条件才可以使用:
网络接口卡须支持加速 RFS。加速 RFS 是由输出 ndo_rx_flow_steer() netdevice 功能的接口卡支持。
ntuple 筛选必须启用。
一旦满足了这些条件,队列映射 CPU 就会基于传统 RFS 配置自动导出。即队列映射 CPU 会基于由每个接收队列的驱动程序配置的 IRQ 关联而自动导出。从 <第 6.3.7 节 “配置 RFS”> 中来获取配置传统 RFS 的信息,红帽推荐在可以使用 RFS 以及网络接口卡支持硬件加速时使用加速 RFS。
5 其他网络调优参数
net.ipv4.tcp_max_tw_buckets
Timewait 的数量,默认为8192
net.ipv4.ip_local_port_range= 1024 65000
允许系统打开的端口范围,前面为下线,后面为上线。默认是 32768 61000
注意: 此可用范围决定了最后timewait状态的链接数量:下面两个选项可有效降低 tw状态链接数量
net.ipv4.tcp_tw_recycle={0|1}
是否启用timeout快速回收:注意: 开启此功能在nat环境下可能会出现严重问题,因为TCP有一种行为,他可以缓冲每个链接最新的时间戳,后续请求如果时间小于缓冲中的时间戳,即被视为无效并丢弃相应的请求报文,Linux是否启用这种行为取决于tcp_timestamp 和 tcp_tw_recycle ,而前一个参数默认是启动的,所以启用后面的参数就会激活此功能,
如果是NAT,为了安全起见,应该禁用tcp_tw_recycle, 另一种解决方案:把tcp_timestamps设置为0.tcp_tw_recycle 设置为1 并不会生效,
net.ipv4.tcp_tw_reuse={0|1}
是否开启tw 重用,即是否允许将time_wait sockets 用于新的TCP 链接
net.ipv4.tcp_sycncookies={0|1}
是否开启SYN cookies , 及当SYN 等待队列溢出时,是够启用cookies 功能 (是否能够尽可能容纳能多请求)
net.ipv4.tcp_timestapms=0
tcp报文时间错,关闭可以避免序列号的卷绕 (防止绕一圈回来的问题)
net.ipv4.tcp_max_syn_backlog= 262144
保存的那些尚未收到客户端确认信息的链接请求的最大值,默认为128,可增大
net.ipv4.tcp_synack_retries= # 表示在服务器端如果没有收到客户端相应时发送数据的次数
为了打开对端链接,内核需要发送一个SYN并附带一个回应前面的一个SYN的ACK, 这业绩所有的三次握手中的第二次,这个设置决定了内核放弃链接之前发送SYN+ACK 包的数量,繁忙的服务器上建议设置为0或者1;
net.ipv4.tcp_syn_Retries=2622144
表示服务器主动发送TCP 链接的次数
在内核中放弃建立连接之前发送SYN包的数量,繁忙的服务器上建议设置为0或者1
net.ipv4.tcp_max_orphans=2622144
系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上,如果超过这个数字,连接将即可被复位毛病发音出警告信息,这个限制仅仅是为了防止简单的Dos,不能过分依赖人文减少这个值,如果需要修改,在确保有足够内存可能的前提下,应该增大此值。
net.ipv4.tcp_fin_timeout=5
如果套接字由本端要求关闭,这个参数决定了我他保持FIN_WAIT-2状态的时间,缺省值是60秒
然而,对端可能会出错或者意外宕机永远不会关闭链接,及时是一个轻量级的web,也可能会有大量的四套接字而内存溢出的风险,fin-wait-2 的危险性比fin-wait-1 要小,因为每个链接最多只能消耗1.5K内存,但是他们的生存期长一些。
net.ipv4.tcp_keepalive_time=30
当keepalive启动的时候,TCP 发送keepalive消息的频度,默认是2小时
以 core 开头的主要用于定义非TCP 相关的缓冲单位是字节
net.core.rmem_max=8388608
定义内核用于所有类型的链接的最大接受缓冲大小
net.core.rmem_Default=65536
定义内核所有类型的链接的默认接受缓冲大小
net.core.wmem_max=8338608
定义内核用于所有类型的链接的最大发送缓冲大小
net.core.wmem_default=65536
定义内核用于所有类型的链接的默认发送缓冲大小
net.ipv4.tcp_mem=’8388608 8388608 8388608 ‘
定义TCP 协议栈使用的内存空间,分别为最小值,默认值和最大值
net.ipv4.tcp_rmem=’4096 37380 8388608
定义TCP 协议栈中用于接受缓冲的内存空间,第一个是最小值,即便当前主机内存空间吃紧,也得保证TCO协议栈至少有次大小的空能空间,第二个值为默认值,他会覆盖net.core.rmem_Default 中为所有协议定义的接受缓冲的大小,第三个值为最大值,既能用于TCP接受缓冲的最大内存空间
net.ipv4.tcp_wmem=’4096 65535 8388608′
定义TCP协议栈用于发送缓冲区的内存空间
5 相关工具详解
1 irqbalance
是一个命令行工具,在处理器中分配硬件中断以提高系统性能,默认设置下再后台程序运行,但只能通过 –oneshot 选项运行一次
以下参数可用于提高性能
–powerthresh
CPU 进入节能模式之前,设定可空闲的 CPU 数量。如果有大于阀值数的 CPU 是大于一个标准的偏差,该差值低于平均软中断工作负载,以及没有 CPU 是大于一个标准偏差,且该偏差高出平均,并有多于一个的 irq 分配给它们,一个 CPU 将处于节能模式。在节能模式中,CPU 不是irqbalance 的一部分,所以它在有必要时才会被唤醒。
–hintpolicy
决定如何解决 irq 内核关联提示。有效值为 exact(总是应用 irq 关联提示)、subset (irq 是平衡的,但分配的对象是关联提示的子集)、或者 ignore(irq 完全被忽略)。
–policyscript
通过设备路径、当作参数的irq号码以及 irqbalance 预期的零退出代码,定义脚本位置以执行每个中断请求。定义的脚本能指定零或多键值对来指导管理传递的 irq 中 irqbalance。
下列是为效键值对:
ban
有效值为 true(从平衡中排除传递的 irq)或 false(该 irq 表现平衡)。balance_level 允许用户重写传递的 irq 平衡度。默认设置下,平衡度基于拥有 irq 设备的 PCI 设备种类。有效值为 none、package、cache、或 core。 numa_node 允许用户重写视作为本地传送 irq 的 NUMA 节点。如果本地节点的信息没有限定于 ACPI,则设备被视作与所有节点距离相等。有效值为识别特定 NUMA 节点的整数(从0开始)和 -1,规定 irq 应被视作与所有节点距离相等。
–banirq
将带有指定中断请求号码的中断添加至禁止中断的列表。
您也可以使用 IRQBALANCE_BANNED_CPUS 环境变量来指定被 irqbalance 忽略的 CPU 掩码。
2 tuna
Tuna 使您能够控制处理器和调度关联。此章节包含命令行界面,但是也可使用有相同功能范围的图形界面。运行命令行 tuna 启动图形工具。
Tuna 接受多种按顺序处理的命令行参数。下列命令将负载分配到四个 socket中。
tuna --socket 0 --isolate \n --thread my_real_time_app --move \n --
irq serial --socket 1 --move \n --irq eth* --socket 2 --spread \n --
show_threads --show_irqs
–gui
打开图形用户界面。
–cpu
取用由 Tuna 控制的 CPU 逗号分隔列表。直到指定新列表前此列表均有效。
–config_file_apply
将配置文件名称应用于系统。
–config_file_list
列出预加载配置文件。
–cgroup
用于连接 –show_threads。如果启用控制组,显示控制组类型,该控制组处理显示带有 –show_threads 所属于的控制组类型。
–affect_children
指定后,Tuna 影响子线程以及父线程。
–filter
过滤显示,只显示受影响的实体。
–isolate
取用 CPU 的逗号分隔列表。Tuna 从指定的 CPU 中迁移线程。
–include
取用 CPU 的逗号分隔列表,Tuna 允许所有线程在指定的 CPU 上运行。
–no_kthreads
指定此参数后,Tuna 不影响内核线程。
–move
将选择的实体移至指定的 CPU 中。
–priority
指定线程调度器策略和优先级。有效调度器策略为 OTHER、FIFO、 RR、BATCH、或者 IDLE。当策略为 FIFO 或者 RR,有效的优先级值为从 1(最低)到 99(最高)的整数。默认值是 1。例如,tuna–threads 7861 –priority=RR:40 为线程 7861 设定了 RR(轮循)的策略和 40 的优先级。
当策略是 OTHER、BATCH、或者 IDLE,唯一有效优先级值为 0,它也是默认值。
–show_threads
显示线程列表。
–show_irqs
显示 irq 列表。
–irqs
取用受 Tuna 影响的 IRQ 逗号分隔列表 。直到指定新列表之前此列表均有效。使用 + 可将 IRQ 添加至列表,使用 – 可从列表中移除。
–save
将内核线程调度保存至指定文件。
–sockets
取用受 Tuna 控制的 CPU socket逗号分隔列表。该选项考虑了系统的拓扑结构,例如共享单一处理器缓存,且在同一个物理芯片上的核心。
–threads
取用受 Tuna 控制的线程逗号分隔列表。直到指定新列表之前此列表均有效。使用 + 可将线程添加至列表,- 可从列表中移除。
–no_uthreads
禁止影响用户线程的操作。
–what_is
更多帮助,请参见选定的实体。
–spread
平均分配 –threads 指定的线程至 –cpus 指定的 CPU。
3 ethtool
ethtool 工具允许管理员查看和编辑网络接口卡设置。这有助于观察某些设备的统计信息,比如被设备丢弃的数据包的数量。
4 ss
ss 是一个命令行工具,显示 socket的统计信息,允许管理员超时访问设备性能。默认设置下,ss 列出打开的非监听且已建立联系的 TCP socket,但向管理员提供一些为筛选掉特定 socket数据的有用选项。
ss -tmpie 是一个常用命令,显示所有 TCP socket(t、内部 TCP 信息(i)、 socket内存使用 (m)、
使用 socket的进程 (p)、和详细的 socket信息(i)。
5 tuned
Tuned 是一个调整的后台程序,在某种工作负载量下通过设置调整配置文件使操作系统有更好的性能表现。
对其进行配置,使其对 CPU 和网络使用的变化做出响应,调整设置以提高激活设备的性能,并减少在未激活设备中的能耗。
在 /etc/tuned/tuned-main.conf 文件中编辑 dynamic_tuning 参数以配置动态调整行为。您也能在调整检查使用和更新调整细节之间,使用 update_interval 参数以秒为单位配置时间。
6 tuned-adm
tuned-adm 是一个命令行工具,提供一些不同配置文件以提高一些特定用例性能。它也提供一个评估系统和输出推荐的调整配置文件的子命令(tuned-adm recommend)。在您系统安装时它也能设置默认配置文
件,以便能用于返回默认配置文件。
自红帽企业版 Linux 7 起,tuned-adm 有能力运行所有命令,这些命令是启用和禁用调整配置文件的一部分。这允许您添加 tuned-adm 中不可用的环境特定检测。例如在选择应用何种调整配置文件之前,检测系统是否是主数据库节点。
红帽企业版 Linux 7 在配置定义文件中提供 include 参数,允许您将自己的 tuned-adm 配置文件建立在存在的配置文件基础上。
以下调整配置文件是随 tuned-adm 一起提供的,并由红帽企业版 Linux 7 支持。
吞吐量性能
服务器配置文件的重点在于提高吞吐量。这是默认配置文件,并是为大多数系统推荐的。
通过设置 intel_pstate 和 max_perf_pct=100,与节约能耗相比,该配置文件更注重性能表现。它能启用透明大页面,使用 cpupower 来设置 performance CPU 频率管理器,并将输入/输出调度器设置为 deadline。它同样将 kernel.sched_min_granularity_ns 设置为10 μ s,将 kernel.sched_wakeup_granularity_ns 设置为 15 μ s,以及将
vm.dirty_ratio 设置 40%。
延迟性能
服务器配置文件的重点在于降低延迟。该配置文件是为延迟敏感的工作负载所推荐的,其中工作负载会从 c- 状态调整和透明大页面增加的 TLB 高效性中获益。
通过设置 intel_pstate 和 max_perf_pct=100,与节约能耗相比,该配置文件更注重性能表现。它能启用透明大页面,使用 cpupower 来设置 performance CPU 频率管理器,并请求值为 1 的 cpu_dma_latency。
网络延迟
服务器配置文件的重点在于降低网络延迟。通过设置 intel_pstate 和 max_perf_pct=100,与节约能耗相比,该配置文件更注重性能表现。它禁用透明大页面以及自动 NUMA 平衡 。它使用 cpupower 来设置 performance CPU 频率管理器,并请求值为 1 的 cpu_dma_latency。它同样将 busy_read 和 busy_poll 的时间设置为 50 μ s,并将 tcp_fastopen 设置为 3。
网络吞吐量
服务器配置文件的重点在于提高网络吞吐量。
通过设置 intel_pstate 和 max_perf_pct=100,与节约能耗,该配置文件更注重性能表现。它能启用透明大页面,使用 cpupower 来设置 performance CPU 频率管理器,它同样将kernel.sched_min_granularity_ns 设置为 10 μ
s,kernel.sched_wakeup_granularity_ns 设置为 15 μ s,以及 vm.dirty_ratio 设置为 40%。
虚拟来宾
虚拟来宾是一个重点在于优化红帽企业版 Linux 7 虚拟机器性能的配置文件。
通过设置 intel_pstate 和 max_perf_pct=100,与节约能耗相比,该配置文件更注重性能表现。它降低了虚拟内存的交换。启用透明大页面,使用 cpupower 来设置 performance CPU频率管理器。它也能将 kernel.sched_min_granularity_ns 设置为 10 μ
s,kernel.sched_wakeup_granularity_ns 设置为 15 μ s,以及将 vm.dirty_ratio设置为 40%。
虚拟-主机
虚拟主机是一个重点在于优化红帽企业版Linux 7虚拟主机的性能的配置文件。
通过设置 intel_pstate 和 max_perf_pct=100,相比节约能耗,该配置文件更注重性能表现。它降低了虚拟内存的交换。它能启用透明大页面,更频繁地重写脏页到磁盘。使用 cpupower来设置 performance CPU 频率管理器,它将 kernel.sched_min_granularity_ns 设置为 10 μ 秒,kernel.sched_wakeup_granularity_ns 设置为 15 μ秒,kernel.sched_migration_cost 设置为 5 μ 秒,以及 vm.dirty_ratio 设置为
40%
7 perf
perf 提供一些有用的指令,此章节列出了其中一些指令。perf 的更多信息请参见《 红帽企业版 7 开发者指
南》, 可在下列网站中查找 http://access.redhat.com/site/documentation/Red_Hat_Enterprise_Linux/ 或者参见手册页。
perf stat
此命令为常见性能事件提供整体数据,包括执行步骤和消耗所用的时间周期。您可使用选项标志来收集事件数据,而非默认测量事件。自红帽企业版 Linux 6.4 起,根据一个或多个特定控制组(c组),可使用 perf stat 筛选监控。
更多信息请参见手册页:
$ man perf-stat
perf record
此命令将性能数据记录到随后可使用 perf report 分析的文件中。更多信息,请参见手册页。$ man perf-record
perf report
此命令从文件中读取性能数据并分析记录数据,更多信息,请参见手册页。
$ man perf-report
perf list
此命令列出特定机器上有效事件。这些事件因系统性能监控硬件和软件配置而异。更多信息,请参见手册页。
$ man perf-list
perf top
此命令执行与 top 工具相似的功能。它实时生成并显示性能计数器配置文件。更多信息,请参见手册页。
$ man perf-top
perf trace
此命令执行与 strace 工具相似的功能。它监控特定线程或进程使用的系统调用以及该应用程序接收的所有信号。可获得其他的跟踪目标。请参见手册页以查看完整列表:
$ man perf-trace
8 x86_energy_perf_policy
x86 energyperfpolicy 工具允许管理员定义性能和能效的相对重要性。由 kernel-tools 软件包提供。
查看当前策略,运行以下命令:
x86_energy_perf_policy -r
设置新策略,运行以下命令:
x86_energy_perf_policy profile_name
用以下配置文件的其中之一替代配置文件名。
performance
处理器不为节能而降低性能。这是默认值。
normal
处理器能容忍由潜在的显著节能所造成的微小性能下降。对于大多数服务器和桌面而言这是合理的节省。
powersave
处理器接受潜在的显著性能下降,以便充分利用能效。
9 turbostat
turbostat 工具提供系统处于不同状态所用时间的详细信息。 Turbostat 由 kernel-tools 软件包提供。
默认设置下,turbostat 为整个系统显示计数器结果的摘要,随后每隔五秒出现计数器结果,以下列标头:
pkg
处理器软件包编号。
core
处理器内核编号。
CPU
LinuxCPU(逻辑处理器)编号。
%c0
cpu 执行完毕的指令间隔百分比。
GHz
当 CPU 处于 c0 状态时,平均时钟速度。
TSC
整个间隔进程中的平均时钟速度。
%c1、 %c3、和 %c6
处理器分别在 c1、c3 或者 c6 状态下间隔百分比。
%pc3 或者 %pc6
处理器分别在 pc3 或者 pc6 状态下的间隔百分比。
使用 -i 选项指定计数器结果间的不同周期,例如:运行 turbostat -i 10 改为每10秒显示结果。
10 numastat
1 概述
numastat 由 numactl 软件包提供,并以每个 NUMA 节点为基础,为处理器和操作系统显示内存统计数据(例如分配时断时续)。
2 numastat 默认跟踪类别
numastat 命令的默认跟踪类别如下所示:
numa_hit
成功分配至该节点的页面数量。
numa_miss
因预期节内存不足分配至该节点的页面数量。每个 numa_miss 事件在另一个节点上都有相应的
numa_foreign 事件。
numa_foreign
原本预期分配至此节点,而改为分配至其他节点的页面数量。numa_foreign 事件在另外节点上,有一个相应的 numa_miss 事件。
interleave_hit
成功分配至该节点、交叉存取策略页面数量。
local_node
由节点上进程成功分配至该节点的页面数量。
other_node
由其他节点的进程分配至该节点的页面数量。
提供以下任一选项会改变按兆字节内存计算的显示单元(约两个小数位),且其他指定的 numastat 行为也会改变,描述如下:
-c
水平浓缩信息的显示表。这有助于含有大量 NUMA 节点的系统,在某种程度上列宽度和列内空间不可预测。使用该选项时,内存的数量四舍五入到最近的兆。
-m
根据单位节点,显示系统范围的内存使用信息,与 /proc/meminfo 中的信息类似。
-n
使用更新的格式、兆为度量单位,显示和如下原始 numastat 命令相同信息:(numa_hit、numa_miss、numa_foreign、interleave_hit、local_node 和 other_node)。
-p pattern
为指定模式显示单位节点内存信息。如果模式的值是由数字组成的,numastat 假定它是数字进程标识符。否则,numastat 从进程命令行查找指定的模式。
假定 -p 选项值后输入的命令行参数是附加模式,目的是将其过滤 。附加模式扩展,而非缩减过滤器。
-s
将显示的数据按降序排列,以便将最大的内存消耗者(根据所有列)列在首位。
您也可指定节点,这样表格将根据节点列分类。使用该选项时,节点值必须马上采用 -s 选项,具体如下:
numastat -s2
不要在选项和其值之间使用空格符。
-v
显示更多冗长的信息。即多进程的进程信息将显示每个进程的细节信息。
-V
显示 numastat 版本信息。
-z
从显示的信息中省略表中只为 0 值的行和列。请注意为了便于显示,一些四舍五入后接近 0 的值不会从显示输出中被省略。
11 numactl
1 概述
Numactl 允许管理员使用指定的调度或内存放置策略来运行进程。Numactl 也能为共享的内存段或文件设置永久策略,以及进程的处理器关联和内存关联。
2 参数
Numactl 提供许多实用的选项。此附录概述一部分选项,也为用户提供了一些使用建议,但并不详细。
–hardware
显示系统中的可用节点,且包含节点间的相对距离的详细目录。
–membind
确保内存只由指定节点分配。如果指定地点没有足够的可用内存,分配会失败。
–cpunodebind
确保指定命令及其子进程只在指定的节点上执行。
–phycpubind
确保指定的命令及其子进程只在指定的处理器上执行。
–localalloc
指明内存应当始终从本地节点分配。
–preferred
指定分配内存的优选节点。如果内存不能从指定的节点分配,其他的节点将被用于回退。
12 numad
1 概述
numad 是一个自动 NUMA 关联管理后台程序。为了动态提高 NUMA 资源分配和管理,它在系统内监控
NUMA 的拓扑结构和资源使用。
注意启用 numad 时 ,其行为将替代默认的自动 NUMA 平衡的行为。
2 在命令行使用 numad
将 numad 作为执行表使用,只需运行:
numad
numad 运行的时候,其活动被记录在 /var/log/numad.log。它会持续运行直到被以下命令终止:
numad -i 0
终止 numad 不会移除它所做的提高 NUMA 关联的变更。如果系统使用有显著的变化,再次运行 numad 能调整关联来提高新条件下的性能。
如需将 numad 管理限制为特定进程,用下列选项来启动它:
numad -S 0 -p pid
-p pid
该选项将指定的 pid 添加到显式的包含列表中。当指定的进程达到 numad 进程的显著门限值,指定的进程才会被管理。
-S 0
它将进程扫描的类型设置为 0,这会将 numad 管理限制到显式包含的进程
3 将 numad 作为服务运行
它尝试基于当前系统的工作负载来动态调整系统。其活动记录在/var/log/numad.log。
如需启动服务,运行:
systemctl start numad.service
如需重启后服务持久,运行:
chkconfig numad on
13 taskset
taskset 工具是由 util-linux 软件包提供的。它允许管理员检索和设置正在运行的进程的处理器关联,或通过
指定的处理器关联运行进程。
重要taskset 不保证本地内存分配。如果您需要本地内存分配的额外性能收益,红帽推荐使用 numactl来替代 taskset。
设置正在运行的进程的 CPU 关联,运行下列命令:
taskset -c processors pid
使用处理器的逗号分隔列表或处理器的范围(例如,1、3、5-7)替换 processors。使用欲重新配置的进程 的进程标识替换 pid 。
用指定的关联运行进程,运行下列命令:
taskset -c processors -- application
用处理器的逗号分隔列表或处理器的范围替换 processors。使用您欲运行的应用程序的命令、选项和参数替换 application。