Linux Performance Tuning

前言

Purpose of Performance Tuning

  • 将系统调节成扮演某个角色。譬如:数据库服务器、WEB服务器、文件服务器、邮件服务器等等。
  • 找到并缓解系统瓶颈
  • 调优指标:响应速度,吞吐量
    • CPU、内存等硬件在最优情况下等达到最高的性能,你必须清楚。

Required Skills

  • Understand both hardware and software
  • Collecting and analysis of measurable relevant data about a performance problem
  • Set proper expectations
  • 5 years full time system management experience

Tuning Efficiency(调优效率)

  • Business Level Tuning

    • Ask right question: “Reduce CPU utilization” or “Business goal”
    • Adjust workflow(调整业务的流程,减少对系统的不必要请求)
    • Removing unused services
      • PC Smart Card Daemon
      • Buletooth and hidd
    • Do i really need the default cron jobs?
      • /etc/cron.daily/makewhatis.cron
      • /etc/cron.daily/mlocate.cron
  • Application Level Tuning

    • Disable or defer expensive operations until analysis?(禁用或延迟对系统而言“很贵的”操作)
      • Disable reverse name lookups
      • Set loglevel to warn for most production daemons
    • Is syslogd a bottleneck?

      • Daemon uses fsync() to flush every file write(系统为保证日志文件不丢失,会立刻调用fsync方法将数据写入磁盘)
      • Disable by prepending hyphen to name of log file in /etc/rsyslog.conf(在日志文件加“-”号,该日志会滞后写入)

      Tips:应用层调优,调的是应用程序本身。譬如你使用nginx、nfs,它们本身有大量的参数可用来调优。在应用层调优远远优于内核调优。

  • Kernel Level Tuning(RH442)

从上往下优化空间越来越小,效果越来越不明显。譬如目前你的WEB Server是apache,调优前首先考虑是否非得使用apache,我们的业务是否是高并发,能不能换成nginx。能够在顶层解决问题,尽量不要希望在底层去解决。

总结

  • 一个命令敲下去,性能提高10%、20%,这是不切合实际的。红帽操作系统已经调优过了,我们是为了某个特定的角色再进行调优。
  • 不同角色的系统有不同调优的参数,不能指望一个参数搞定所有事情。
  • 物理级别的缺陷,比如硬盘、网卡等由于寿命原因性能大幅下降,则系统层面调优见效甚微。

Understand Hardware

Computer System Architecture

computer_architecture

  • CPU
    • 运算器
    • 控制器(指令、数据存储过程)
    • 寄存器(Register)
  • North bridge(寻址)

CPU

X86架构机器三个特点(RH442)

  • I/O Address

    X86架构CPU把外设寄存器看做是一个独立的地址空间,访问内存的指令不能用来访问这些外设寄存器,而需要用专用的指令(如IN、OUT指令),称为“I/O端口”。不同外设使用不同“I/O端口”,PCI总线就能知道是哪个外设了,当然“I/O端口”会被消耗完。

    Power PC、ARM的CPU把外设寄存器看做是内存的一部分、寄存器参与内存统一编址,通过一般的内存指令来访问这些外设寄存器,称为“I/O内存”。

  • IRQ(中断请求)
  • DMA(直接内存访问)

    DMA主要功能是传输数据,但是不需要占用CPU(不需要中断)。传输数据从外设到存储器或者从存储器到存储器。

    在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题。即DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU。

    完整的DMA传输过程必须经过下面的4个步骤 :

    1. DMA请求

      CPU对DMA控制器初始化,并向I/O接口发出操作命令,I/O接口提出DMA请求。

    2. DMA响应

      DMA控制器对DMA请求判别优先级及屏蔽,向总线裁决逻辑提出总线请求。当CPU执行完当前总线周期即可释放总线控制权。此时,总线裁决逻辑输出总线应答,表示DMA已经响应,通过DMA控制器通知I/O接口开始DMA传输。

    3. DMA传输

      DMA控制器获得总线控制权后,CPU即刻挂起或只执行内部操作,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。在DMA控制器的控制下,在和外部设备之间直接进行数据传送,在传送过程中不需要的参与。开始时需提供要传送的数据的起始位置和数据长度。

    4. DMA结束

      当完成规定的成批数据传送后,DMA控制器即释放总线控制权,并向I/O接口发出结束信号。当I/O接口收到结束信号后,一方面停止I/O设备的工作,另一方面向CPU提出中断请求,使CPU从不介入的状态解脱,并执行一段检查本次DMA传输操作正确性的代码。最后,带着本次操作结果及状态继续执行原来的程序。

      由此可见,DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU的效率大为提高。

      参考:DMA原理

扩展小知识:

内存中起始16M空间,是留给DMA使用的,用于把数据装载进内存空间低地址空间。内存中另有1M空间是给BIOS预留,计算机有自举功能,用于初始化足够的软件来查找并加载功能完整的操作系统。

查看CPU

  • 总览

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    [root@yadoom ~]# lscpu 
    Architecture: x86_64 #x86架构
    CPU op-mode(s): 32-bit, 64-bit
    Byte Order: Little Endian
    CPU(s): 40 #逻辑CPU个数
    On-line CPU(s) list: 0-39
    Thread(s) per core: 2 #每核的线程数
    Core(s) per socket: 10 #每颗CPU的核数
    Socket(s): 2 #物理CPU个数
    NUMA node(s): 2 # NUMA节点数
    Vendor ID: GenuineIntel
    CPU family: 6
    Model: 79
    Model name: Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
    Stepping: 1
    CPU MHz: 1200.093
    BogoMIPS: 4805.86
    Virtualization: VT-x
    L1d cache: 32K #一级数据缓存
    L1i cache: 32K #一级指令缓存
    L2 cache: 256K #二级缓存
    L3 cache: 25600K #三级缓存
    NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38
    NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39
  • 核数

    1
    2
    3
    4
    5
    6
    7
    8
    [root@yadoom ~]# grep CPU /proc/cpuinfo
    model name : Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
    model name : Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
    ......
    model name : Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
    model name : Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
    [root@yadoom ~]# grep CPU /proc/cpuinfo | wc -l
    40

CPU架构

  • SMP架构:Symmetric Multi-Processor

大多数早期的单处理机系统的设计为让每个 CPU 到每个内存位置都使用同一逻辑路径(一般是平行总线)。这样每次 CPU 访问任意位置的内存时与其他系统中的 CPU 对内存的访问消耗的时间是相同的。此类架构就是我们所说的对称多处理器(SMP)系统。SMP 适合 CPU 数较少的系统,但一旦 CPU 计数超过某一点(8 或者 16),要满足对内存的平等访问所需的平行 trace 数就会使用过多的板载资源,留给外设的空间就太少。

uma

  • UNMA架构:Non-Uniform Memory Access

不是为每个处理器包提供对等的内存访问,而是让每个包/插槽组合有一个或者多个专用内存区以便提供高速访问。每个插槽还有到另一个插槽的互联以便提供对其他插槽内存的低速访问。

下图中 CPU0 访问左边的内存条大约需要三个时钟周期:一个周期是将地址发给内存控制器,一个周期是设置对该内存位置的访问,一个周期是读取或者写入到该位置。但 CPU1 可能需要 6 个时钟周期方可访问内存的同一位置,因为它位于不同的插槽,必须经过两个内存控制器:插槽 1 中的本地内存控制器和插槽 0 中的远程内存控制器。如果在那个位置出现竞争(即如果有一个以上 CPU 同时尝试访问同一位置),内存控制器需要对该内存进行随机且连续的访问,所以内存访问所需时间会较长。添加缓存一致性(保证本地 CPU 缓存包含同一内存位置的相同数据)会让此过程更为复杂。

numa

numa

扩展小知识:当CPU有多颗时,物理CPU常见通讯方法有三种

  • FSB(传统的前端总线,常用于PC机)
  • QPI(intel)
  • HyperTransport(AMD)
  • MPP架构:Massive Parallel Processing

大规模并行处理系统,它由多个 SMP 服务器通过节点互联网络连接,协同工作,完成相同的任务,从用户的角度来看是一个服务器系统。每个节点内的CPU都有自己私有的资源,如总线,内存,硬盘等。在每个节点内都有操作系统和管理数据库的实例复本。这种结构最大的特点在于不共享资源。

在 MPP 系统中,每个 SMP 节点也可以运行自己的操作系统、数据库等,是一种完全无共享 (Share Nothing) 结构。但和 NUMA 不同的是,它不存在异地内存访问的问题。换言之,每个节点内的 CPU 不能访问另一个节点的内存。节点之间的信息交互是通过节点互联网络实现的,这个过程一般称为数据重分配 (Data Redistribution) 。节点互联网仅供 MPP 服务器内部使用,对用户而言是透明的。

Numa Architecture

查看Numa node

1
2
3
4
5
6
7
8
9
10
11
12
[root@yadoom ~]# numactl --hardware
available: 2 nodes (0-1) # 当前机器有2个NUMA node,编号0、1
node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
node 0 size: 32722 MB # 物理内存大小
node 0 free: 2352 MB # 当前free内存大小
node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
node 1 size: 32768 MB
node 1 free: 12314 MB
node distances: # node距离,可以简单认为Node内部访问及跨Node访问的成本
node 0 1
0: 10 20 # 由此可知跨node访问内存的成本是 内部访问的2倍
1: 20 10

查看node

  • node0包含的CPU

    1
    2
    3
    [root@yadoom ~]# ls -l /sys/devices/system/node/node0/
    cpu0/ cpu12/ cpu16/ cpu2/ cpu22/ cpu26/ cpu30/ cpu6/ cpulist
    cpu10/ cpu14/ cpu18/ cpu20/ cpu24/ cpu28/ cpu4/ cpu8/ cpumap
  • /sys/devices/system/cpu

    系统的 CPU 是如何互相连接的信息。

  • /sys/devices/system/node

    系统中 NUMA 节点以及那些节点间相对距离的信息。

查看cpu cache

1
2
3
4
5
6
[root@yadoom ~]# ls -l /sys/devices/system/cpu/cpu0/cache/
total 0
drwxr-xr-x 2 root root 0 Nov 10 2017 index0 # 1级数据cache
drwxr-xr-x 2 root root 0 Nov 3 2017 index1 # 1级指令cache
drwxr-xr-x 2 root root 0 Nov 3 2017 index2 # 2级cache
drwxr-xr-x 2 root root 0 Nov 10 2017 index3 # 3级cache, 对应cpuinfo里的cache

目录里的文件是cache信息描述,以本机的cpu0/index0为例简单解释一下:












































文件 内容 说明
type Data 数据cache,如果查看index1就是Instruction
Level 1 L1
Size 32K 大小为32K
coherency_line_size 64 64 4 128=32K
physical_line_partition 1
ways_of_associativity 4
number_of_sets 128
shared_cpu_map 00000101 表示这个cache被CPU0和CPU8 share

解释一下shared_cpu_map内容的格式,表面上看是2进制,其实是16进制表示,每个bit表示一个cpu,1个数字可以表示4个cpu
截取00000101的后4位,转换为2进制表示。

CPU id 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0×0101的2进制表示 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1

0101表示cpu8和cpu0,即cpu0的L1 data cache是和cpu8共享的。

再看一下index3 shared_cpu_map的例子

1
2
# cat /sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_map
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000f0f
CPU id 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0x0f0f的2进制表示 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1

cpu0,1,2,3和cpu8,9,10,11共享L3 cache。

查看numa状态

1
2
3
4
5
6
7
8
[root@yadoom ~]# numastat
node0 node1
numa_hit 1011487518 716368222
numa_miss 0 145365467
numa_foreign 145365467 0
interleave_hit 20673 20631
local_node 1011487341 716343592
other_node 177 145390097

上述可知node 0的unma_miss过高,可考虑用numactl将进程和CPU绑定。详见CPU调优章节。

参数 说明
numa_hit 为这个节点成功的分配尝试数。
numa_miss 由于在目的节点中内存较低而尝试为这个节点分配到另一个节点的数目。每个 numa_miss 事件都在另一个节点中有对应的 numa_foreign 事件。
numa_foreign 最初要为这个节点但最后分配个另一个节点的分配数。每个 numa_foreign 事件都在另一个节点中有对应的 numa_miss 事件。
interleave_hit 成功分配给这个节点的尝试交错策略数。
local_node 这个节点中的进程成功在这个节点中分配内存的次数。
other_node 这个节点中的进程成功在另一个节点中分配内存的次数。
1
2
3
4
5
6
7
[root@yadoom ~]# numactl --show
policy: default
preferred node: current
physcpubind: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
cpubind: 0 1
nodebind: 0 1
membind: 0 1

查看内存numa node分布

1
2
cat /proc/<pid>/numa_maps
cat /proc/$(pidof pname|cut -d "" -f1)/numa_maps

查看线程run在哪个processor

1
2
3
4
top -p $(pidof pname|sed -e 's/ /,/g')

在默认配置下不显示线程信息,需要进入Top后按“shift+H”,打开线程显示。
另外,如果没有P列,还需要按“f”,按“j”,添加,这一列显示的数字就是这个线程上次run的processor id。

https://blog.jcole.us/2010/09/28/mysql-swap-insanity-and-the-numa-architecture/
https://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/

numad

numad 是一个自动 NUMA 亲和性管理守护进程,它监控系统中的 NUMA 拓扑以及资源使用以便动态提高 NUMA 资源分配和管理(以及系统性能)。

numad 不会在进程只运行几分钟或者不会消耗很多资源时改进性能。

有连续不可预测内存访问的系统,比如大型内存中的数据库也不大可能从 numad 使用中受益。

CPU Cache

Levels of CPU Caches

  • Level 1 private cache(on cpu chip)
    • SRAM(static memory):集成度低(存储相同的数据,静态RAM的体积是动态RAM的6倍),价格高(同容量的静态RAM是动态RAM的四倍)
  • Level 2 private or shared cache(on cpu chip)
    • DRAM(high speed dynamic memory)
  • Level 3 private or shared cache(usually on mainboard)
    • shared between cores inside a CPU socket
  • Level 4 fully shared cache
    • shared between CPU sockets

Cache Memory Types

内存和缓存的关联地址。

  • Direct Mapped Cache
    a memory location can be cached into one cache line.(一个内存地址,只能被映射到缓存的一个区域。)
  • Full Associative Cache
    a memory location can be cached into any cache line.(一个内存地址,可以被映射到缓存所有区域。)
  • n-Way Associative Cache
    Fair,most used, a memory location can be cached into any one of n cache lines.

n-way-associative-cache

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@kvm-2 ~]# x86info -c
x86info v1.25. Dave Jones 2001-2009
Feedback to <davej@redhat.com>.

Found 8 CPUs
--------------------------------------------------------------------------
CPU #1
EFamily: 0 EModel: 3 Family: 6 Model: 62 Stepping: 4
CPU Model: Unknown model.
Processor name string: Intel(R) Xeon(R) CPU E5-2609 v2 @ 2.50GHz
Type: 0 (Original OEM) Brand: 0 (Unsupported)
Number of cores per physical package=16
Number of logical processors per socket=32
Number of logical processors per core=2
APIC ID: 0x0 Package: 0 Core: 0 SMT ID 0
Cache info
TLB info
Instruction TLB: 4K pages, 4-way associative, 128 entries. # 4路关联
Data TLB: 4KB pages, 4-way associative, 64 entries
64 byte prefetching.
Found unknown cache descriptors: 63 76 ca ff
--------------------------------------------------------------------------

查看CPU Cache

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
[root@yadoom ~]# lscpu 
Architecture: x86_64 #x86架构
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 8 #逻辑CPU个数
On-line CPU(s) list: 0-7
Thread(s) per core: 1 #每核的线程数
Core(s) per socket: 4 #每颗CPU的核数
Socket(s): 2 #物理CPU个数
NUMA node(s): 2 # NUMA节点数
Vendor ID: GenuineIntel
CPU family: 6
Model: 62
Stepping: 4
CPU MHz: 2499.904
BogoMIPS: 4999.28
Virtualization: VT-x
L1d cache: 32K #一级数据缓存
L1i cache: 32K #一级指令缓存
L2 cache: 256K #二级缓存
L3 cache: 10240K #三级缓存
NUMA node0 CPU(s): 0,2,4,6
NUMA node1 CPU(s): 1,3,5,7
[root@yadoom ~]# lscpu -p
# The following is the parsable format, which can be fed to other
# programs. Each different item in every column has an unique ID
# starting from zero.
# CPU,Core,Socket,Node,,L1d,L1i,L2,L3 # “Node”表示NUMA nodes
0,0,0,0,,0,0,0,0
1,1,1,1,,1,1,1,1
2,2,0,0,,2,2,2,0
3,3,1,1,,3,3,3,1
4,4,0,0,,4,4,4,0
5,5,1,1,,5,5,5,1
6,6,0,0,,6,6,6,0
7,7,1,1,,7,7,7,1

[root@yadoom ~]# dmidecode -t 7
# dmidecode 2.11
SMBIOS 2.7 present.

Handle 0x0700, DMI type 7, 19 bytes
Cache Information
Socket Designation: Not Specified
Configuration: Enabled, Not Socketed, Level 1
Operational Mode: Write Through
Location: Internal
Installed Size: 128 kB #一级缓存(32k * 4)
Maximum Size: 128 kB
Supported SRAM Types:
Unknown
Installed SRAM Type: Unknown
Speed: Unknown
Error Correction Type: Single-bit ECC
System Type: Data
Associativity: 8-way Set-associative

Handle 0x0701, DMI type 7, 19 bytes
Cache Information
Socket Designation: Not Specified
Configuration: Enabled, Not Socketed, Level 2
Operational Mode: Write Through
Location: Internal
Installed Size: 1024 kB #二级缓存(256k * 4)
Maximum Size: 1024 kB
Supported SRAM Types:
Unknown
Installed SRAM Type: Unknown
Speed: Unknown
Error Correction Type: Single-bit ECC
System Type: Unified
Associativity: 8-way Set-associative

Handle 0x0702, DMI type 7, 19 bytes
Cache Information
Socket Designation: Not Specified
Configuration: Enabled, Not Socketed, Level 3
Operational Mode: Write Back
Location: Internal
Installed Size: 10240 kB #与lscpu数值一样,说明4核共享三级缓存
Maximum Size: 10240 kB
Supported SRAM Types:
Unknown
Installed SRAM Type: Unknown
Speed: Unknown
Error Correction Type: Single-bit ECC
System Type: Unified
Associativity: 20-way Set-associative

由上输出可得知该服务器的L1,L2是每个核心独享的,L3是共享的。

疑问

  • CPU如何读取RAM中的数据?

    答:使用CPU Cache(缓存)。CPU将数据从RAM拷贝到L3缓存,再一次拷贝到L2缓存、L1数据缓存,最后到寄存器中。

  • CPU Cache置换算法

    置换算法影响因素:程序局部性

    • 空间局部性:
    • 时间局部性:数据很可能会再短时间内被再次访问。
    • LRU(Least recently used)

      最近最少使用算法,这个缓存算法将最近使用的条目存放到靠近缓存顶部的位置。当一个新条目被访问时,LRU将它放置到缓存的顶部。当缓存达到极限时,较早之前访问的条目将从缓存底部开始被移除。

    • MRU(Most recently used)

      最近最常使用算法,将使用时间距离现在最近的那条记录替换掉。

  • CPU如何更新数据?

    答:CPU依次更新L1、L2、L3缓存对应的数据,最后更新RAM。

  • CPU Cache写机制

    • write through

      cpu向cache写入数据时,同时向memory(后端存储)也写一份,使cache和memory的数据保持一致。优点是简单;缺点是每次都要访问memory,速度比较慢。

    • write back

      cpu更新cache时,只是把更新的cache区标记一下,并不同步更新memory。当cache要被置换出去时,才去更新memory(后端存储)。优点是数据写入速度快,因为不需要写存储;缺点是一旦更新后的数据未被写入存储时出现系统掉电的情况,数据将无法找回。

Memory

  • Memory size,max allowed

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    [root@yadoom ~]# free
    total used free shared buffers cached
    Mem: 90743596 23288228 67455368 0 684452 2938648
    -/+ buffers/cache: 19665128 71078468
    Swap: 26214392 0 26214392

    [root@yadoom ~]# more /proc/meminfo
    MemTotal: 263860344 kB # 已经减去了显卡占用的内存
    MemFree: 206924460 kB
    MemAvailable: 248609828 kB
    Buffers: 145604 kB
    Cached: 51754488 kB
    SwapCached: 0 kB
    Active: 45933660 kB
    Inactive: 7115240 kB
    Active(anon): 8130140 kB
    Inactive(anon): 4851368 kB
    Active(file): 37803520 kB
    Inactive(file): 2263872 kB

    [root@yadoom ~]# dmidecode -t 17
    # dmidecode 2.11
    SMBIOS 2.7 present.

    Handle 0x1100, DMI type 17, 34 bytes
    Memory Device
    Array Handle: 0x1000
    Error Information Handle: Not Provided
    Total Width: 72 bits
    Data Width: 64 bits
    Size: 8192 MB # 内存大小
    Form Factor: DIMM
    Set: 1
    Locator: DIMM_A1
    Bank Locator: Not Specified
    Type: DDR3 # DDR3代
    Type Detail: Synchronous Registered (Buffered)
    Speed: 1333 MHz # 时钟频率
    Manufacturer: 00CE04B300CE
    Serial Number: 4400B1EA
    Asset Tag: 01104611
    Part Number: M393B1K70CH0-YH9
    Rank: 2
    Configured Clock Speed: 1333 MHz
    ......
  • bandwidth and letency

    • DDR2(2 bits),DDR3(4 bits),DDR4(8 bits)
    • Bandwidth = Clock rate(时钟频率) 4(DDR3) 2(Double) * bits / 8(Double就是D,脉冲升频降会各取一次数据。带宽无需手动计算,内存卡会标识PC xxxxMB)
    • Letency(wait time before read again,in ns)读取内存时,要等待的时间。动态内存需要电门不停的刷,所以读取数据需要时间。
    • ECC(slower,safer)
      • Corrects single-bit errors
      • Detects multiple-bit errors
  • Method of memory accessing
    • UMA,NUMA

Storage

  • Type of storage used
    • mechanical magnetic platters(机械磁盘)
    • SSD devices(固态磁盘)
  • Hardware RAID Level
    • stripe depth(条带深度)
    • stripe width(条带宽度)
    • stripe size = stripe depth × stripe width
  • Direct-attached Storage(直连存储)
    • SATA,SAS,IDE
  • SCSI,Fibre Channel,ISCSI
    • Bandwidth,latency,multipath

磁盘架构

  • 架构概述

    硬盘中包含多个硬盘盘片,硬盘盘片为圆形,每个硬盘盘片都有一个可以读写的磁头(Head),将这个磁头固定,使硬盘盘片旋转一周,所走轨迹就是磁道(Track)。硬盘内所有盘片的相同磁道号的集合成为磁柱(Cylinder)。每一磁道被划分成许多区域,每个区域叫一个扇区(Sector)。扇区是硬盘的最小存储物理量,一个扇区的存储容量大约是512字节(约0.5K)。

    • geometry

      geometry应该翻译为几何数据,其实就是指的CHS(Cylinder、Head、Sector/Track) 。

      • Cylinder(每面盘片上有几条磁道)
      • Head(磁头数量,也就是几面盘片。)
      • Sector/Track(每条磁道上有几个扇区)
    • sector
    • block

      disk-geometry
      disk-terminology

  • Capacity

    • CLV(Constant Linear Velocity)
    • CAV(Constant Angular Velocity)
    • Zoned CAV

      storage-discs-capacity

扩展小知识:

Linux里文件的文件名、文件属性、文件内容是分别存储的:文件名存放在目录项(即dentry)中,文件属性存放在inode中,一般情况下,每个inode占用128Bity磁盘空间,文件内容存放在block中。每个block最多存放一个文件,而当一个block存放不下的情况下,会占用下一个block。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 总容量:heads * cylinders * sectors * Sector size
[root@localhost ~]# fdisk -l /dev/sda

Disk /dev/sdd: 299.4 GB, 299439751168 bytes
255 heads, 63 sectors/track, 36404 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00056494
......
[root@localhost ~]# tune2fs -l /dev/sda1 | grep Block
Block count: 204800
Block size: 1024
Blocks per group: 8192
1
2
3
4
5
6
[root@localhost ~]# vmstat 1 3
procs -----------memory---------- ---swap-- ----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 260352448 34480 2212952 0 0 0 1 2 3 0 0 100 0 0
0 0 0 260352192 34480 2212956 0 0 0 0 124 177 0 0 100 0 0
0 0 0 260352192 34480 2212956 0 0 0 0 27 44 0 0 100 0 0

bi bo 的单位是块,但是它不是操作系统里的那个块,它表示物理磁盘的块(sector,扇区),每个扇区 512 字节。

磁盘外圈速度比里圈速度快得多,所以操作系统默认将swap分区分配在里圈。

磁盘速度

一般都指Burst speed(顺序读写)速率。

storage-bandwidth

磁盘类型

  • IDE(并口)

    IDE(Integrated Drive Electronics电子集成驱动器)的缩写,它的本意是指把控制器与盘体集成在一起的硬盘驱动器,是一种硬盘的传输接口,它有另一个名称叫做ATA(Advanced Technology Attachment),这两个名词都有厂商在用,指的是相同的东西。

    IDE的规格后来有所进步,而推出了EIDE(Enhanced IDE)的规格名称,而这个规格同时又被称为Fast ATA。所不同的是Fast ATA是专指硬盘接口,而EIDE还制定了连接光盘等非硬盘产品的标准。而这个连接非硬盘类的IDE标准,又称为ATAPI接口。而之后再推出更快的接口,名称都只剩下ATA的字样,像是Ultra ATA、ATA/66、ATA/100等。

  • SATA(串口)

    SATA(Serial ATA)口的硬盘又叫串口硬盘。2001年,由Intel、APT、Dell、IBM、希捷、迈拓这几大厂商组成的Serial ATA委员会正式确立了Serial ATA 1.0规范。

    SATA接口需要硬件芯片的支持,例如Intel ICH5(R)、VIA VT8237、nVIDIA的MCP RAID和SiS964,如果主板南桥芯片不能直接支持的话,就需要选择第三方的芯片,例如Silicon Image 3112A芯片等,不过这样也就会产生一些硬件性能的差异,并且驱动程序也比较繁杂。

  SATA的优势:支持热插拔,传输速度快,执行效率高。

  • SCSI(小型计算机系统专用接口)

    SCSI的英文全称为“Small Computer System Interface”(小型计算机系统接口),是同IDE(ATA)完全不同的接口,IDE接口是普通PC的标准接口,而SCSI并不是专门为硬盘设计的接口,是一种广泛应用于小型机上的高速数据传输技术。SCSI接口具有应用范围广、多任务、带宽大、CPU占用率低,以及热插拔等优点,但较高的价格使得它很难如IDE硬盘般普及,因此SCSI硬盘主要应用于中、高端服务器和高档工作站中。

  • SAS(就是串口的SCSI接口)

    SAS(Serial Attached SCSI)即串行连接SCSI,是新一代的SCSI技术。和现在流行的Serial ATA(SATA)硬盘相同,都是采用串行技术以获得更高的传输速度,并通过缩短连结线改善内部空间等。SAS是并行SCSI接口之后开发出的全新接口。此接口的设计是为了改善存储系统的效能、可用性和扩充性,并且提供与SATA硬盘的兼容性。

  • FC(光纤通道)

    光纤通道的英文拼写是Fiber Channel,和SCIS接口一样光纤通道最初也不是为硬盘设计开发的接口技术,是专门为网络系统设计的,但随着存储系统对速度的需求,才逐渐应用到硬盘系统中。光纤通道硬盘是为提高多硬盘存储系统的速度和灵活性才开发的,它的出现大大提高了多硬盘系统的通信速度。光纤通道的主要特性有:热插拔性、高速带宽、远程连接、连接设备数量大等。

  • SSD(固态硬盘)

    固态硬盘(Solid State Disk或Solid State Drive),也称作电子硬盘或者固态电子盘,是由控制单元和固态存储单元(DRAM或FLASH芯片)组成的硬盘。固态硬盘的接口规范和定义、功能及使用方法上与普通硬盘的相同,在产品外形和尺寸上也与普通硬盘一致。由于固态硬盘没有普通硬盘的旋转介质,因而抗震性极佳。其芯片的工作温度范围很宽(-40~85℃)。

    由于固态硬盘技术与传统硬盘技术不同,所以产生了不少新兴的存储器厂商。厂商只需购买NAND存储器,再配合适当的控制芯片,就可以制造固态硬盘了。新一代的固态硬盘普遍采用SATA-2接口。

查看磁盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@yadoom ~]# fdisk -l /dev/sda 

Disk /dev/sda: 4000.8 GB, 4000787030016 bytes
255 heads, 63 sectors/track, 486401 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

[root@yadoom ~]# lspci
......
00:1f.0 ISA bridge: Intel Corporation C600/X79 series chipset LPC Controller (rev 05)
00:1f.2 SATA controller: Intel Corporation C600/X79 series chipset 6-Port SATA AHCI Controller (rev 05)
......

[root@yadoom ~]# hdparm -I /dev/sda

/dev/sda:

ATA device, with non-removable media
Model Number: ST1000NM0033-9ZM173 # 希捷1T
Serial Number: Z1W3VQXC
Firmware Revision: GA0A
Transport: Serial, SATA Rev 3.0
Standards:
Supported: 9 8 7 6 5
Likely used: 9
......
[root@yadoom ~]# dmesg |grep -C5 SATA

SSD

  • Electronic disk, no moving mechanical(机械) components
  • No startup time
  • Very low latency
  • Potentially longer life time(尽可能延长寿命)
    • Wear leveling(磨损平衡):闪存寿命是以P/E(完全擦写)次数来计算的,而WL就是确保闪存内每个块被写入的次数相等的一种机制。
  • Parameter
    • TBW
      • 在 SSD 使用寿命结束之前指定工作量可以写入 SSD 的总数据量。
    • DWPD
      • 在保固期内(或不同的数年时段内)每天可以写入硬盘用户存储容量的次数。
      • DWPD = (固态硬盘的 TBW (TB) P/E) / (365 天 年数 * 固态硬盘用户容量 (GB))

SSD Types

固态硬盘就是靠NAND Flash闪存芯片存储数据的,这点类似于我们常见的U盘。NAND Flash根据存储原理分为三种,SLC、MLC、TLC。

  • SLC

    Single-Level Cell ,即1bit/cell(1个存储器储存单元可存放1 bit的数据),速度快寿命长,价格超贵(约MLC 3倍以上的价格),约10万次擦写寿命

  • MLC

    Multi-Level Cell,即2bit/cell,速度一般寿命一般,价格一般,约1000–3000次擦写寿命

  • TLC

    Trinary-Level Cell,即3bit/cell,也有Flash厂家叫8LC,速度慢寿命短,价格便宜,约1000次擦写寿命。
    单位容量的存储器,可以存储更多的数据,所以TLC每百万字节生产成本是最低的。

案例:计算256G的TLC固态硬盘的使用寿命。

假设该硬盘每天读取100G数据,256G*1000/356/100G=7.19(年)

SSD Garbage Collection

ssd-garbage-collection

  1. 上图SSD中有两个空的(erased)的Block X和Block Y, 每个Block有12个Pages;
  2. 首先在Block X中写入4个Pages(A, B, C, D);
  3. 接着再向Block X中写入新的4个pages(E, F, G, H), 同时写入PageA-D的更新数据(A’, B’, C’, D’), 这时PageA-D变为失效数据(invalid);
  4. 为了向PageA-D的位置写入数据,需要将E, F, G, H, A’, B’, C’, D’ 8个pages先搬到Block Y中, 之后再把Block X erase掉,这个过程就为GC。

Nand flash 以Page为单位读写数据,而以Block为单位擦除数据。

不过,由于GC的过程增加了数据的读写过程,势必会对SSD的performance的产生一定的影响,所以GC发生的条件与触发点很关键。

GC触发条件大致有3点:

  1. Spare Block()备用块太少
  2. Wear leveling
  3. 处理ECC错误Block

SSD Trim

操作系统删除数据时,Windows只会做个标记,说明这里已经没东西了,等到真正要写入数据时再来真正删除,并且做标记这个动作会保留在磁盘缓存中,等到磁盘空闲时再执行;Linux只会把inode table回收。

所以对于非空的page,SSD在写入前必须先进行一次Erase,则写入过程为read-erase-modify-write:将整个block的内容读取到cache中,整个block从SSD中Erase,要覆写的page写入到cache的block中,将cache中更新的block写入闪存介质,这个现象称之为写入放大(write amplification)。

为了解决这个问题,SSD开始支持TRIM,TRIM功能使操作系统得以通知SSD哪些页不再包含有效的数据。

当Windows识别到SSD并确认SSD支持Trim后,在删除数据时,会不向硬盘通知删除指令,只使用Volume Bitmap来记住这里的数据已经删除。Volume Bitmap只是一个磁盘快照,其建立速度比直接读写硬盘去标记删除区域要快得多。这一步就已经省下一大笔时间了。然后再是写入数据的时候,由于NAND闪存保存数据是纯粹的数字形式,因此可以直接根据Volume Bitmap的情况,向快照中已删除的区块写入新的数据,而不用花时间去擦除原本的数据。

  • Linux启用Trim

    1. 确认 SSD 、操作系统、文件系统都支持 TRIM

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      # discard_granularity 非 0 表示支持
      [root@yadoom ~]# cat /sys/block/sda/queue/discard_granularity
      0
      [root@yadoom ~]# cat /sys/block/nvme0n1/queue/discard_granularity
      512

      # DISC-GRAN (discard granularity) 和 DISC-MAX (discard max bytes) 列非 0 表示该 SSD 支持 TRIM 功能。
      [root@yadoom ~]# lsblk --discard
      NAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
      sda 0 0B 0B 0
      ├─sda1 0 0B 0B 0
      ├─sda2 0 0B 0B 0
      └─sda3 0 0B 0B 0
      sr0 0 0B 0B 0
      nvme0n1 512 512B 2T 1
      nvme1n1 512 512B 2T 1
    2. 开启

      1
      2
      3
      对于 ext4 文件系统,可以在/etc/fstab里添加 discard 参数来启用 TRIM,添加前请确认你的 SSD 支持 TRIM。
      [root@yadoom ~]# vim /etc/fstab
      /dev/sdb1 /data1 ext4 defaults,noatime,discard 0 0
  • Windows启用Trim

注意:如果SSD组RAID0后,将失去Trim功能。

RAID

  • striping(条带化)

    条带(strip)是把连续的数据分割成相同大小的数据块,把每段数据分别写入到阵列中的不同磁盘上的方法。简单的说,条带是一种将多个磁盘驱动器合并为一个卷的方法。 许多情况下,这是通过硬件控制器来完成的。

  • why striping?

    首先介绍什么是磁盘冲突。当多个进程同时访问一个磁盘时,磁盘的访问次数(每秒的 I/O 操作,IOPS)和数据传输率(每秒传输的数据量,TPS)达到极限后,后面的进程就需要等待,这时就是所谓的磁盘冲突。

    避免磁盘冲突是优化 I/O 性能的一个重要目标,而 I/O 性能的优化与其他资源(如CPU和内存)的优化有着很大的区别,I/O 优化最有效的手段是将 I/O 最大限度的进行平衡。

    条带化技术就是一种自动的将 I/O 的负载均衡到多个物理磁盘上的技术,条带化技术就是将一块连续的数据分成很多小部分并把他们分别存储到不同磁盘上去。这就能使多个进程同时访问数据的多个不同部分而不会造成磁盘冲突,而且在需要对这种数据进行顺序访问的时候可以获得最大程度上的 I/O 并行能力,从而获得非常好的性能。

  • stripe width

    条带宽度:是指同时可以并发读或写的条带数量。这个数量等于RAID中的物理硬盘数量。例如一个经过条带化的,具有4块物理硬盘的阵列的条带宽度就是 4。增加条带宽度,可以增加阵列的读写性能。道理很明显,增加更多的硬盘,也就增加了可以同时并发读或写的条带数量。

  • stripe depth(stripe unit)

    条带深度:指的是条带的大小。这个参数指的是写在每块磁盘上的条带数据块的大小。RAID的数据块大小一般在2KB到512KB之间(或者更大),其数值是 2 的次方,即2KB,4KB,8KB,16KB这样。

    条带大小对性能的影响比条带宽度难以量化的多:

    1. 减小条带大小: 由于条带大小减小了,则文件被分成了更多个,更小的数据块。这些数据块会被分散到更多的硬盘上存储,因此提高了传输的性能,但是由于要多次寻找不同的数据块,磁盘定位的性能就下降了。
    2. 增加条带大小: 与减小条带大小相反,会降低传输性能,提高定位性能。

      根据上边的论述,我们会发现根据不同的应用类型,不同的性能需求,不同驱动器的不同特点(如SSD硬盘),不存在一个普遍适用的”最佳条带大小”。所以这也是存储厂家,文件系统编写者允许我们自己定义条带大小的原因。

  • stripe size

    有时也称block size块大小、chunk size簇大小、stripe length条带长度、granularity粒度,是单块磁盘上的每次I/O的最小单位。

案例:Raid1+0 stripe size for MySQL InnoDB

RAID卡

  • 写策略 write-through和write-back

    • write-through

      数据在写入存储的同时,要写入缓存,这种方式安全但是会牺牲写性能,因为只有等数据完全落入硬盘后,才算是一次io完成,这个过程会造成cpu的iowait。

    • write-back

      数据直接写入缓存,写缓存的速度是远远大于写磁盘的,所以这种方式可以提高服务器的写性能。也许你会想当断电了怎么办?不用担心,raid卡是有电池的,完全可以支持缓存中的数据再写入磁盘。除非点背,raid卡电池也没电了。

      我们生产环境用的就是write-back,就是并且还设置了force write-back (即使电池没电了,也要写缓存),这样有了点冒险,但是大幅度的提高了写性能,我觉得利大于弊吧。

  • 读策略read policy

    • No-Read-Ahead(非预读)
    • Read-ahead(预读)
      提前加载数据到缓存,加速顺序读请求。
    • Adaptive(自适应)
      如果最近两次的磁盘访问都落在了连续的扇区内那就采用Read-ahead,否则就采用No-Read-ahead。
  • Disk cache Policy
    磁盘上的缓存,区别于raid卡的缓存,该项SAS和SATA一般都是关的,因为掉电了有可能会丢数据,ssd可以打开。

Networking Profile

查看网卡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@yadoom ~]# lspci | grep Ethernet
01:00.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe
01:00.1 Ethernet controller: Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe
02:00.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe
02:00.1 Ethernet controller: Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe
# 示:四块博通千兆网卡

[root@yadoom ~]# ethtool bond0
Settings for bond0:
Supported ports: [ ]
Supported link modes: Not reported
Supported pause frame use: No
Supports auto-negotiation: No
Advertised link modes: Not reported
Advertised pause frame use: No
Advertised auto-negotiation: No
Speed: 1000Mb/s
Duplex: Full # 当前工作在全双工模式
Port: Other
PHYAD: 0
Transceiver: internal
Auto-negotiation: off
Link detected: yes

[root@yadoom ~]# ip addr show bond0
6: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether f8:bc:12:48:91:64 brd ff:ff:ff:ff:ff:ff
inet6 fe80::fabc:12ff:fe48:9164/64 scope link
valid_lft forever preferred_lft forever

主板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@yadoom ~]# dmidecode -t baseboard
# dmidecode 2.11
SMBIOS 2.7 present.

Handle 0x0200, DMI type 2, 9 bytes
Base Board Information
Manufacturer: Dell Inc.
Product Name: 0DCWD1
Version: A02
Serial Number: ..CN1374043800AE.
Asset Tag: Not Specified

Handle 0x2900, DMI type 41, 11 bytes
Onboard Device
Reference Designation: Integrated NIC 1
Type: Ethernet
Status: Enabled
Type Instance: 1
Bus Address: 0000:01:00.0
......

PCI设备

PCI是CPU和外围设备通信的高速传输总线。

pci-express-link-performance

链接:PCI_Express

  • GT/s
    它是QPI(QuickPath Interconnect)的数据传输单位,类似于MHz相对于FSB。QPI是intel推出i7时所使用的数据总线。

    FSB与QPI都是前端数据总线,区别是QPI的传输速率比FSB的传输速率快一倍。QPI总线采用的是2:1比率,意思就是实际的数据传输速率两倍于实际的总线时钟速率。所以6.4GT/s的总线速率其实际的总线时钟频率是 3.2GHz。

    FSB的传输速率单位实际上是MT/s,通常我们所说的总线传输速率单位MHz是我们习惯上的称呼,是对时钟频率单位的挪用。

    一开始的时候总线频率是与数据传输速率一致的,比如33MHz的总线的总线时钟频率是33MHz。但是后来从Pentium Pro开始,FSB采用”quad pumped”四倍并发技术做了改良。所谓quad pumped 就是说在每个总线时钟周期内传送四次数据,也就是说总线的数据传输速率等于总线时钟频率的4倍,如果是333MHz的时钟频率的总线那么其数据传输速率为1333MT/s(即是1.333GT/s),但是我们习惯上还是称为1333MHz。

    GT/s,它明确地表明的是QPI总线实际的数据传输速率而不是时钟频率。

查看pci设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
[root@yadoom ~]# lspci            # pciutils软件包
7f:08.0 System peripheral: Intel Corporation Xeon E5 v2/Core i7 QPI Link 0 (rev 04)
......
7f:0c.1 System peripheral: Intel Corporation Xeon E5 v2/Core i7 Unicast Registers (rev 04)
......
7f:16.2 System peripheral: Intel Corporation Xeon E5 v2/Core i7 Broadcast Registers (rev 04)

[root@yadoom ~]# lspci -vt
-+-[0000:7f]-+-08.0 Intel Corporation Xeon E5 v2/Core i7 QPI Link 0
| +-09.0 Intel Corporation Xeon E5 v2/Core i7 QPI Link 1
......
| +-0f.0 Intel Corporation Xeon E5 v2/Core i7 Integrated Memory Controller 0 Target Address/Thermal Registers
......
| +-10.7 Intel Corporation Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 3
| +-13.0 Intel Corporation Xeon E5 v2/Core i7 R2PCIe
| +-13.1 Intel Corporation Xeon E5 v2/Core i7 R2PCIe
| +-13.4 Intel Corporation Xeon E5 v2/Core i7 QPI Ring Registers
| +-13.5 Intel Corporation Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring
| +-16.0 Intel Corporation Xeon E5 v2/Core i7 System Address Decoder
| +-16.1 Intel Corporation Xeon E5 v2/Core i7 Broadcast Registers
| \-16.2 Intel Corporation Xeon E5 v2/Core i7 Broadcast Registers
\-[0000:00]-+-00.0 Intel Corporation Xeon E5 v2/Core i7 DMI2
+-01.0-[02]--+-00.0 Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe
| \-00.1 Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe
+-01.1-[01]--+-00.0 Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe
| \-00.1 Broadcom Corporation NetXtreme BCM5720 Gigabit Ethernet PCIe
+-02.0-[04]--
+-02.2-[03]----00.0 LSI Logic / Symbios Logic MegaRAID SAS 2008 [Falcon]
+-03.0-[05]--
+-03.2-[06]--
+-05.0 Intel Corporation Xeon E5 v2/Core i7 VTd/Memory Map/Misc
+-05.2 Intel Corporation Xeon E5 v2/Core i7 IIO RAS
+-11.0-[07]--
+-16.0 Intel Corporation C600/X79 series chipset MEI Controller #1
+-16.1 Intel Corporation C600/X79 series chipset MEI Controller #2
+-1a.0 Intel Corporation C600/X79 series chipset USB2 Enhanced Host Controller #2
+-1c.0-[08]--
+-1c.7-[09-0d]----00.0-[0a-0d]--+-00.0-[0b-0c]----00.0-[0c]----00.0 Matrox Electronics Systems Ltd. G200eR2
| \-01.0-[0d]--
+-1d.0 Intel Corporation C600/X79 series chipset USB2 Enhanced Host Controller #1
+-1e.0-[0e]--
+-1f.0 Intel Corporation C600/X79 series chipset LPC Controller
\-1f.2 Intel Corporation C600/X79 series chipset 6-Port SATA AHCI Controller

[root@yadoom ~]# lspci -xxx -s 7f:13.5 # x越多,列出的信息越详细
7f:13.5 Performance counters: Intel Corporation Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring (rev 04)
00: 86 80 36 0e 00 00 00 00 04 00 01 11 10 00 80 00
......

[root@yadoom ~]# lspci -vv -s 7f:13.5 # v越多,列出的信息越详细
7f:13.5 Performance counters: Intel Corporation Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring (rev 04)
Subsystem: Dell Device 048c
Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-

USB设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@yadoom ~]# lsusb           # usbutils包
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 003: ID 0624:0248 Avocent Corp. Virtual Hub
Bus 001 Device 004: ID 0624:0249 Avocent Corp. Virtual Keyboard/Mouse

[root@yadoom ~]# lsusb -vt
Bus# 2
`-Dev# 1 Vendor 0x1d6b Product 0x0002
`-Dev# 2 Vendor 0x8087 Product 0x0024
Bus# 1
`-Dev# 1 Vendor 0x1d6b Product 0x0002
`-Dev# 2 Vendor 0x8087 Product 0x0024
`-Dev# 3 Vendor 0x0624 Product 0x0248
`-Dev# 4 Vendor 0x0624 Product 0x0249

查看内核产生的硬件日志

  • /var/log/dmesg
    系统启动,一次性将启动时关于硬件的kernel日志写入该文件。
  • dmesg命名
    实时记录kernel日志,譬如插入USB设备,可使用dmesg命令查看。

获取硬件命令汇总

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1. CPU型号
dmidecode -t 4| awk '/Version/ && /CPU/'|uniq
2. CPU核数
grep -c 'processor' /proc/cpuinfo
sysctl kern.smp.cpus|awk '{print $2}'
3.内存大小
free -m|awk '/Mem/{printf("%d\n", $2/1024+0.5)}'
sysctl hw.physmem|awk '{printf ("%d\n", $2/1073741824+0.5)}'
4.硬盘总大小
fdisk -l|awk '/Disk \/dev\//{sum +=$3}END{printf("%d\n", sum+0.5)}'
sysctl kern.geom.conftxt|grep -Eo 'DISK \w+ \w+'|awk '{sum +=$3}END{printf("%d\n", sum/1000000000+0.5)}'
df -Pm | awk '/^\/dev\//{sum +=$2}END{printf("%d\n", sum/1024+0.5)}'
5.主板型号
dmidecode -t 1| awk '/Product Name/'
6.取主板Serial
dmidecode -t 1|awk '/Serial/'

一句话脚本:
dmidecode -t 4| awk '/Version:/'|tail -n1

if [ `uname` == Linux ];then grep -c 'processor' /proc/cpuinfo;else sysctl kern.smp.cpus|awk '{print $2}';fi

if [ `uname` == Linux ];then free -m|awk '/Mem/{printf("%d\n", $2/1000+0.5)}';else sysctl hw.physmem|awk '{printf ("%d\n", $2/1073741824+0.5)}';fi

if [ `uname` == Linux ];then fdisk -l|awk '/Disk \/dev\//{sum +=$3}END{printf("%d\n", sum+0.5)}';else sysctl kern.geom.conftxt|egrep -o 'DISK \w+ \w+'|awk '{sum +=$3}END{printf("%d\n", sum/1000000000+0.5)}';fi

dmidecode -t 1| awk '/Product Name/'

System Tuning

Stoarge

Storage is very slow compare to memory. Linux has two way to compensate the issue.

  • Caching
    • Read from memory, write to memory
    • Read can be cached, write can be deferred
  • I/O Schedulers
    • Kernel attempt to recorder, coalesce I/O requests(临近扇区,合并读请求)
    • Minimize relocating magnetic head(最小化磁头的动作,重新定位)

I/O Tuning

Tuning Theory

  • L: Queue length: average number of requests waiting in the system
  • A: Arrival rate: the rate at which requests enter a system
  • W: Wait time: average time to satisfy a request
    • also known as wall clock,latency,response time, or residence time

L = A * W

Queue Length

  • Requests are buffered in memory
  • L may be read-write tunable or a read-only measurement

Wait Time

  • Includes
    • Queue time(排队时间)
    • Service time(服务时间)
  • Tactics(策略)
    • Reduce queue time
    • Reduce service time

L = A W = A (Tq + Ts)

Service Time

  • Includes
    • Sysem time: time in kernel mode
    • User time: time in user mode(doing useful work)
  • Tactics
    • Reduce system time(blocks user mode operations)
    • spend as much time as needed in user mode

L = A W = A (Q + S) = A * (Tq + (Tsys + Tuser))

Summary of Queue Theory

  • L: Queue length
  • A: Arrival rate(requests/second)
  • W: Wait time(latency, time to satisfy a request)
  • Q: Queue time
  • S: Service time(includes system time, user time)
  • C: Complete rate(requests/second)

    • Steady state: A = C
    • L = A W = A (Q + S) = A * (Tq + (Tsys + Tuser))

Summary of strategies

  • Tune L
    • Constrain queue length
    • Sort the queue to prefer reads
  • Tune A or C
    • Reduce visit count by distributing across multiple resources(SMP,RAID)
    • Defer resource visits until think time(lazy write)
    • Improve throughput for resource(more efficient protocol, less overhead)
  • Tune W
    • Use expiration time for requests
    • use resources with smaller service time(in-memory cache vs disk)

I/O Scheduler

参考:http://www.cnblogs.com/cobbliu/p/5389556.html

  • cfq(Complete Fair Queuing)

    • default schduler after kernel 2.6.18

      它试图为竞争块设备使用权的所有进程分配一个请求队列和一个时间片,在调度器分配给进程的时间片内,进程可以将其读写请求发送给底层块设备,当进程的时间片消耗完,进程的请求队列将被挂起,等待调度。

      每个进程的时间片和每个进程的队列长度取决于进程的IO优先级,每个进程都会有一个IO优先级,CFQ调度器将会将其作为考虑的因素之一,来确定该进程的请求队列何时可以获取块设备的使用权。IO优先级从高到低可以分为三大类:RT(real time),BE(best try),IDLE(idle),其中RT和BE又可以再划分为8个子优先级。

      实际上,我们已经知道CFQ调度器的公平是针对于进程而言的,而只有同步请求(read或syn write)才是针对进程而存在的,他们会放入进程自身的请求队列,而所有同优先级的异步请求,无论来自于哪个进程,都会被放入公共的队列,异步请求的队列总共有8(RT)+8(BE)+1(IDLE)=17个。

    • IO Priority

      • Class 1(real time): first-access to disk, can starve(饿死) other classes
        • 0-7: The scheduling class data
      • Class 2(best-effort): round-robin access, the default
        • 0-7: The scheduling class data
      • Class 3(idle): receives disk I/O only if no other requests in queue

      ionice命令可调节进程的IO优先级

      1
      2
      3
      4
      ionice -n0 -c1 -p pid
      ionice -n7 -c2 -p pid
      ionice -c3 -p pid # 我不入地狱,谁入地狱
      ionice -c 2 -n 0 bash # Runs ’bash’ as a best-effort program with highest priority.
  • deadline

    • with predictable service time(可预见的服务时间)
    • for virtualization host

      Deadline算法中引入了四个队列,这四个队列可以分为两类,每一类都由读和写两类队列组成,一类队列用来对请求按起始扇区序号进行排序,通过红黑树来组织,称为sort_list;另一类对请求按它们的生成时间进行排序,由链表来组织,称为fifo_list。每当确定了一个传输方向(读或写),那么将会从相应的sort_list中将一批连续请求dispatch到requst_queue的请求队列里,具体的数目由fifo_batch来确定。只有下面三种情况才会导致一次批量传输的结束:

    1. 对应的sort_list中已经没有请求了
    2. 下一个请求的扇区不满足递增的要求
    3. 上一个请求已经是批量传输的最后一个请求了

      所有的请求在生成时都会被赋上一个期限值(根据jiffies),并按期限值排序在fifo_list中,读请求的期限时长默认为为500ms,写请求的期限时长默认为5s,可以看出内核对读请求是十分偏心的,其实不仅如此,在deadline调度器中,还定义了一个starved和writes_starved,writes_starved默认为2,可以理解为写请求的饥饿线,内核总是优先处理读请求,starved表明当前处理的读请求批数,只有starved超过了writes_starved后,才会去考虑写请求。因此,假如一个写请求的期限已经超过,该请求也不一定会被立刻响应,因为读请求的batch还没处理完,即使处理完,也必须等到starved超过writes_starved才有机会被响应。为什么内核会偏袒读请求?这是从整体性能上进行考虑的。读请求和应用程序的关系是同步的,因为应用程序要等待读取的内容完毕,才能进行下一步工作,因此读请求会阻塞进程,而写请求则不一样,应用程序发出写请求后,内存的内容何时写入块设备对程序的影响并不大,所以调度器会优先处理读请求。

      默认情况下,读请求的超时时间是500ms,写请求的超时时间是5s。

      这篇文章说在一些多线程应用下,Deadline算法比CFQ算法好。这篇文章说在一些数据库应用下,Deadline算法比CFQ算法好。

  • anticipatory(AS)

    • wait for a while after read request
    • for sequential read workloads(大量顺序读的)

      Anticipatory算法从Linux 2.6.33版本后,就被移除了,因为CFQ通过配置也能达到Anticipatory算法的效果。

  • noop(No Operation)

    • quick to response, low CPU overhead
    • for SSD,virtualization guests(宿主机使用了deadline,则虚拟机使用noop,因为真正写盘操作是主机完成)

      Noop调度算法也叫作电梯调度算法,它将IO请求放入到一个FIFO队列中,然后逐个执行这些IO请求,当然对于一些在磁盘上连续的IO请求,Noop算法会适当做一些合并。这个调度算法特别适合那些不希望调度器重新组织IO请求顺序的应用。

      这种调度算法在以下场景中优势比较明显:

    1. 在IO调度器下方有更加智能的IO调度设备。如果您的Block Device Drivers是Raid,或者SAN,NAS等存储设备,这些设备会更好地组织IO请求,不用IO调度器去做额外的调度工作;

      1. 上层的应用程序比IO调度器更懂底层设备。或者说上层应用程序到达IO调度器的IO请求已经是它经过精心优化的,那么IO调度器就不需要画蛇添足,只需要按序执行上层传达下来的IO请求即可。

      2. 对于一些非旋转磁头氏的存储设备,使用Noop的效果更好。因为对于旋转磁头式的磁盘来说,IO调度器的请求重组要花费一定的CPU时间,但是对于SSD磁盘来说,这些重组IO请求的CPU时间可以节省下来,因为SSD提供了更智能的请求调度算法,不需要内核去画蛇添足。

I/O Scheduler Manage

  • /sys/block/\<device>/queue/scheduler
    切换I/O调度算法。

    1
    2
    [root@yadoom ~]# cat /sys/block/sda/queue/scheduler 
    noop anticipatory deadline [cfq]
  • 每种调度算法的可调参数

    1
    2
    3
    4
    5
    # 该目录会根据不同Schduler而变化
    [root@yadoom ~]# cd /sys/block/sda/queue/iosched/
    [root@yadoom iosched]# ls
    back_seek_max fifo_expire_async group_idle low_latency slice_async slice_idle
    back_seek_penalty fifo_expire_sync group_isolation quantum slice_async_rq slice_sync
  • CFQ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /sys/block/<device>/queue/iosched/slice_idle 
    当一个进程的队列被分配到时间片却没有 IO 请求时,调度器在轮询至下一个队列之前的等待时间,以提升 IO 的局部性,对于 SSD 设备,可以将这个值设为 0

    /sys/block/<device>/queue/iosched/quantum
    一个进程的队列每次被处理 IO 请求的最大数量,默认为 4,RHEL6 为 8,增大这个值可以提升并行处理 IO 的性能,但可能会造成某些 IO 延迟问题。

    /sys/block/<device>/queue/iosched/slice_async_rq
    一次处理写请求的最大数

    /sys/block/<device>/queue/iosched/low_latency
    如果IO延迟的问题很严重,将这个值设为 1
  • Deadline

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /sys/block/<device>/queue/iosched/writes_starved 
    进行一个写操作之前,允许进行多少次读操作

    /sys/block/<device>/queue/iosched/read_expire
    读请求的过期时间,默认为 5ms

    /sys/block/<device>/queue/iosched/write_expire
    写请求的过期时间,默认为 500ms

    /sys/block/sda/queue/iosched/front_merges
    是否进行前合并
  • Anticipatory

    1
    2
    3
    4
    5
    6
    7
    8
    /sys/block/<device>/queue/iosched/antic_expire 
    预测等待时长,默认为 6ms

    /sys/block/<device>/queue/iosched/{write_expire,read_expire}
    读写请求的超时时长

    /sys/block/<device>/queue/iosched/{write_batch_expire,read_batch_expire}
    读写的批量处理时长

Queue

  • /sys/block/\<device>/queue/nr_requests

    磁盘请求队列长度(一次性交给磁盘的请求数量)。增大它会牺牲更多内存。

    1
    2
    [root@yadoom ~]# cat /sys/block/sda/queue/nr_requests 
    128
  • /sys/block/\<device>/queue/read_ahead_kb

    预先读数据块大小,对于大量的连续读业务,可以增大它。

Kernel Module

Module commands

  • lsmod

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    [root@yadoom ~]# lsmod 
    Module Size Used by
    tcp_diag 1041 0
    inet_diag 8735 1 tcp_diag # 表示该模块被tcp_diag依赖,使用次数为1
    ip6table_filter 2889 0
    ip6_tables 18732 1 ip6table_filter
    ebtable_nat 2009 0
    ebtables 18135 1 ebtable_nat
    ipt_MASQUERADE 2466 3
    iptable_nat 6158 1
    nf_nat 22759 2 ipt_MASQUERADE,iptable_nat
    nf_conntrack_ipv4 9506 4 iptable_nat,nf_nat
    nf_defrag_ipv4 1483 1 nf_conntrack_ipv4
    xt_state 1492 1
    nf_conntrack 79758 5 ipt_MASQUERADE,iptable_nat,nf_nat,nf_conntrack_ipv4,xt_state
    ipt_REJECT 2351 2
  • /lib/modules/\<kernel-release>/kernel/

    内核模块所在目录。

  • modinfo [ modulename… ]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [root@yadoom ~]# modinfo sx8
    filename: /lib/modules/2.6.32-431.el6.x86_64/kernel/drivers/block/sx8.ko
    version: 1.0
    description: Promise SATA SX8 block driver
    license: GPL
    author: Jeff Garzik
    srcversion: 4772099AB984FE59198263E
    alias: pci:v0000105Ad00008002sv*sd*bc*sc*i*
    alias: pci:v0000105Ad00008000sv*sd*bc*sc*i*
    depends:
    vermagic: 2.6.32-431.el6.x86_64 SMP mod_unload modversions
    parm: max_queue:Maximum number of queued commands. (min==1, max==30, safe==1) (int)
  • modprobe [ modulename… ]

  • rmmod [ modulename… ]

Modules parameters

  • 查看某模块有哪些参数可调整

    1
    2
    3
    4
    5
    6
    7
    8
    [root@yadoom ~]# modinfo -p usb_storage
    quirks:supplemental list of device IDs and their quirks
    delay_use:seconds to delay before using a new device
    swi_tru_install:TRU-Install mode (1=Full Logic (def), 2=Force CD-Rom, 3=Force Modem)
    option_zero_cd:ZeroCD mode (1=Force Modem (default), 2=Allow CD-Rom

    [root@yadoom ~]# modinfo -p sx8
    max_queue:Maximum number of queued commands. (min==1, max==30, safe==1)
  • 自定义参数

    1
    2
    3
    4
    [root@yadoom ~]# cat /etc/modprobe.d/my.conf 
    options usb_storage delay_use=3
    options st buffer_kbs=128
    options sx8 max_queue=10
  • 使用modprobe命令重新加载这些模块,自定义的参数就会生效

    1
    2
    3
    [root@yadoom ~]# modprobe usb_storage
    [root@yadoom ~]# modprobe st
    [root@yadoom ~]# modprobe sx8
  • Check runtime module parameters

    • /sys/module/\/parameters/
  • Automatically loading modules

    • /etc/sysconfig/modules/my.modules
    • Linux init脚本会执行以上目录下modules结尾的文件。

      1
      modprobe usb_storage|st|sx8

Tuned

  • Tune a system on the fly as needed
  • Based on tuning profiles
    • max power saving
    • max disk performance
    • self made profile allowed(允许自定义tune方案)
    • profile can even has monitoring program to run(还支持运行监控程序)
  • SysV service
    • tuned
    • ktune
  • Can be used with crond to switch between profiles
    • 0 7 * 1-5 /usr/bin/tuned-adm profile throughput-performance
    • 0 20 * 1-5 /usr/bin/tuned-adm profile server-powersave

Use Tuned

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@cmdb-192-168-21-241 ~]# cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core)

[root@yadoom ~]# tuned-adm active
Current active profile: virtual-guest

[root@yadoom ~]# tuned-adm list
Available profiles:
- balanced - General non-specialized tuned profile
- desktop - Optimize for the desktop use-case
- latency-performance - Optimize for deterministic performance at the cost of increased power consumption
- network-latency - Optimize for deterministic performance at the cost of increased power consumption, focused on low latency network performance
- network-throughput - Optimize for streaming network throughput, generally only necessary on older CPUs or 40G+ networks
- powersave - Optimize for low power consumption
- throughput-performance - Broadly applicable tuning that provides excellent performance across a variety of common server workloads
- virtual-guest - Optimize for running inside a virtual guest
- virtual-host - Optimize for running KVM guests
Current active profile: virtual-guest

[root@yadoom ~]# tuned-adm profile powersave
  • latency-performance

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [root@yadoom ~]# grep -vE '^#|^$' /usr/lib/tuned/latency-performance/tuned.conf 
    [main]
    summary=Optimize for deterministic performance at the cost of increased power consumption
    [cpu]
    force_latency=1
    governor=performance
    energy_perf_bias=performance
    min_perf_pct=100
    [sysctl]
    kernel.sched_min_granularity_ns=10000000
    vm.dirty_ratio=10
    vm.dirty_background_ratio=3
    vm.swappiness=10
    kernel.sched_migration_cost_ns=5000000
  • throughput-performance

Custom Tuning Profiles

1
2
3
4
5
6
7
8
9
10
11
12
[root@yadoom ~]# cd /usr/lib/tuned/
[root@yadoom ~]# mkdir test-performance

[root@yadoom ~]# vim test-performance/tuned.conf
[main]
include=latency-performance
summary=Test profile that uses settings for latency-performance tuning profile

[root@yadoom ~]# tuned-adm list
......
- test-performance - Test profile that uses settings for latency-performance tuning profile
......

CPU Tuning

CPU模式

  • 内核模式

    Ring0,Core程序运行。

  • 用户模式

    Ring3,用户进程运行。该模式的进程无法直接操作硬件,通过系统调用,由内核程序翻译后调用。

扩展小知识: 完全虚拟化如何让虚拟机认为自己直接运行在主机上?

答:引入了-1环(硬件虚拟化),使虚拟机管理程序运行在-1环,虚拟机操作系统就可以运行在Ring0。

CPU Scheduler

  • FF SCHED_FIFO: 先进先出的实时进程
  • RR SCHED_RR: 循环的实时进程
  • TS SCHED_OTHER (SCHED_NORMAL): 调度算法为CFQ。普通的共享时间进程,用户态进程。
1
2
3
4
5
6
7
[root@kvm-2 ~]# ps -e -o class,cmd
CLS CMD
TS /sbin/init
TS [kthreadd]
FF [migration/0]
TS [ksoftirqd/0]
FF [migration/0]

Scheduler Priority

  • Real-time process (SCHED_FIFO/SCHED_RR) real-time priority
    • 1 (lowest priority) to 99 (higest priority)。
  • Conventional process static priority(SCHED_NORMAL)
    • 100 (highest priority) to 139 (lowest priority)。nice值可动态调整该值。
    • Conventional process’s static priority = (120 + Nice value)
    • By default, conventional process starts with nice value of 0 which equals static priority 120
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@kvm-2 ~]# ps -e -o class,rtprio,pri,nice,cmd
CLS RTPRIO PRI NI CMD
TS - 19 0 /sbin/init # RTPRIO 为"-",说明该进程没有实时优先级
TS - 19 0 [kthreadd] # PRI 为19,说明它静态优先级为 100+19+0=119
FF 99 139 - [migration/0] # CLS是FF,说明它是实时优先级 99
TS - 19 0 [ksoftirqd/0]
......
TS - 19 0 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
TS - 19 0 irqbalance --pid=/var/run/irqbalance.pid
TS - 19 0 rpcbind
TS - 19 0 dbus-daemon --system
TS - 19 0 NetworkManager --pid-file=/var/run/NetworkManager/NetworkManager.pid
TS - 19 0 /usr/sbin/modem-manager
TS - 19 0 rpc.statd
TS - 19 0 /usr/sbin/acpid # 大多数用户进程,优先级都为 119
  • dynamic priority

    指内核监控长时间未运行的(TS类别)进程,临时调高它的优先级(nice值),避免进程饥饿。相反地,也会惩罚长时间占用cpu的进程。

    dynamic priority = max (100, min ( static priority - bonus + 5, 139))

    bonus is ranging from 0 to 10, which is set by scheduler depends on the past history of the process; more precisely, it is related to the average sleep time of the process.

Scheduler Priority Changing

  • Changing Real-time/Conventional process priority.
1
2
3
4
5
6
7
8
#Real-time process 
$chrt 80 ps -e -o class,rtprio,pri,nice,cmd
..
FF 80 120 - ps -e -o class,rtprio,pri,nice,cmd
# Conventional process
$nice -n 10 ps -e -o class,rtprio,pri,nice,cmd
...
TS - 12 10 ps -e -o class,rtprio,pri,nice,cmd

Interrupt and IRQ

中断请求(IRQ)是用于服务的请求,在硬件层发出。可使用专用硬件线路或者跨硬件总线的信息数据包(消息信号中断,MSI )发出中断。启用中断后,接收 IRQ 后会提示切换到中断上下文。

CPU绑定后,它仍然要服务于中断。应该将中断绑定至那些非隔离的CPU上,从而避免那些隔离的CPU处理中断程序;

/proc/interrupts文件列出每个I/O 设备中每个 CPU 的中断数,每个 CPU 核处理的中断数,中断类型,以及用逗号分开的注册为接收中断的驱动程序列表。(详情请参考 proc(5) man page:man 5 proc)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@yadoom ~]# cat /proc/interrupts 
CPU0 CPU1
0: 14678 0 IO-APIC-edge timer
1: 2 0 IO-APIC-edge i8042
4: 2 0 IO-APIC-edge
7: 0 0 IO-APIC-edge parport0
8: 1 0 IO-APIC-edge rtc0
9: 0 0 IO-APIC-fasteoi acpi
12: 4 0 IO-APIC-edge i8042
14: 45394223 0 IO-APIC-edge ata_piix
15: 0 0 IO-APIC-edge ata_piix
16: 56 16232636 IO-APIC-fasteoi i915, p2p1
18: 5333843 11365439 IO-APIC-fasteoi uhci_hcd:usb4
20: 2277759 0 IO-APIC-fasteoi ata_piix
21: 3 0 IO-APIC-fasteoi ehci_hcd:usb1, uhci_hcd:usb2
22: 0 0 IO-APIC-fasteoi uhci_hcd:usb3
23: 3813 6412 IO-APIC-fasteoi uhci_hcd:usb5, Intel ICH7
......
# APIC表示高级可编程中断控制器(Advanced Programmable Interrupt Controlle)
# APIC是SMP体系的核心,通过APIC可以将中断分发到不同的CPU 来处理。
# i915:Intel i915 集成显卡驱动

Soft Interrupt and Context Switch

上下文切换(也称做进程切换或任务切换)是指 CPU 从一个进程或线程切换到另一个进程或线程。

CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再次加载这个任务的状态,从任务保存到再加载的过程就是一次上下文切换。

查看中断

1
2
mpstat
dstat -c

将IRQ绑定CPU

1
2
3
4
echo CPU_MASK > /proc/irq/<irq number>/smp_affinity

# 案例:将CPU中断绑定到CPU #0,#1上。
echo 3 > /proc/irq/<irq number>/smp_affinity

将IRQ绑定到某个CPU,那么最好在系统启动时,将那个CPU隔离起来,不被scheduler通常的调度。
可以通过在Linux kernel中加入启动参数:isolcpus=cpu-list将CPU隔离起来。

IRQ Irqbalance

irqbalance用于优化中断分配,它会自动收集系统数据以分析使用模式,并依据系统负载状况将工作状态置于 Performance mode 或 Power-save mode。处于Performance mode 时,irqbalance 会将中断尽可能均匀地分发给各个 CPU core,以充分利用 CPU 多核,提升性能。

处于Power-save mode 时,irqbalance 会将中断集中分配给第一个 CPU,以保证其它空闲 CPU 的睡眠时间,降低能耗

但是在实时系统中会导致中断自动漂移,对性能造成不稳定因素,在高性能的场合建议关闭。

1
/etc/init.d/irqbalance stop

查看上下文切换

1
2
sar -w           # 查看上下文切换的平均次数,以及进程创建的平均值
vmstat 1 3 # 每秒上下文切换次数

如何减少上下文切换

既然上下文切换会导致额外的开销,因此减少上下文切换次数便可以提高多线程程序的运行效率。减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程。

- 无锁并发编程。多线程竞争时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash取模分段,不同的线程处理不同段的数据
- CAS算法。Java的Atomic包使用CAS算法来更新数据,而不需要加锁
- 使用最少线程。避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态
- 协程。在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换

CPU Iffinity(姻亲关系)

当软中断和上下文切换过大时。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
taskset
mask 二进程 #CPU
0x0000 0001 0001:node 0
0x0000 0003 0011:node 01
0x0000 0005 0101:node 02
0x0000 0007 0111:node 0-2

[root@yadoom ~]# taskset -p mask pid
101, 3# CPU
[root@yadoom ~]# taskset -p 0x00000005 101

绑定进程101,CPU 0-2#、7#
taskset -p -c 0-2,7 101

# 指定CPU启动进程
taskset mask -- program
taskset -c 0,5,7-9 – myprogram

CPU 子系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@yadoom ~]# mkdir /cpusets
[root@yadoom ~]# vim /etc/fstab
cpuset /cpusets cpuset defaults 0 0
[root@yadoom ~]# mount -a
[root@yadoom ~]# ls /cpusets/
cgroup.clone_children cgroup.sane_behavior cpuset.mem_exclusive cpuset.memory_pressure cpuset.memory_spread_slab cpuset.sched_relax_domain_level tasks
cgroup.event_control cpuset.cpu_exclusive cpuset.mem_hardwall cpuset.memory_pressure_enabled cpuset.mems notify_on_release
cgroup.procs cpuset.cpus cpuset.memory_migrate cpuset.memory_spread_page cpuset.sched_load_balance release_agent
#
[root@yadoom ~]# cat /cpusets/cpuset.cpus
0-3

# 创建子域
[root@yadoom ~]# mkdir /cpusets/domain1
[root@yadoom ~]# ls /cpusets/domain1/
......
[root@yadoom ~]# echo 0-1 >/cpusets/domain1/cpuset.cpus #将CPU #0,#1绑定进来
[root@yadoom ~]# echo 0 >/cpusets/domain1/cpuset.mems #将内存绑定进来
[root@yadoom ~]# echo #pid /cpusets/domain1/tasks #将某个进程绑定进来,该进程只能在CPU 0-1上运行

[root@yadoom ~]# ps -e -o psr,pid,cmd

Memory Tuning

Memory Management

  • An important thing for kernel to do
  • Paping(分页) is the way to manage system memory
    • Memory is organized into pages
    • For x86, normal page size is 4KiB(4096 Bytes)
  • Processes do not address physical memory directly, each process has a virtual address space
    • 32-bit: 4GiB maximum memory a process can have
    • 64-bit: 16EiB maximum memory a process can have
  • Process can only see physical pages that have been mapped into its virtual address, so security enforced(进程间是隔离的)
  • Virtual page must translate to physical page in order to access data.

VSZ vs. RSS

  1. when process requests memory, only reserve virtual memory address, but does not actually map them to physical pages UNTIL they are used.

    • Virtual memory used: VIRT, VSIZE, VSZ
    • Physical memory used: RES, RSS
  2. Processes can share memory by mapping same physical pages to their private virtual address space, kernel takes control(进程可以共享同一片物理内存)

VIRT vs RES vs SHR

  • VIRT – Virtual Memory Size (KiB)

    The total amount of virtual memory used by the task. It includes all code, data and shared libraries plus pages that have been swapped out and pages that have been mapped but not used.(一个任务使用的虚拟内存的总量,包括 代码、数据、共享库加上已换出的页和已经被映射出去了但是还没被使用的页。 简单理解就是所有的虚拟内存中含有共享库、共享内存、堆、栈和所有已经申请的内存空间。)

    1
    2
    3
    4
    5
    6
    7
    # 利用命令查看:vsz=data + code + shared lib
    $ ps -a -o pid,pmem,cmd,vsz,drs,trs
    PID %MEM CMD VSZ DRS TRS
    3870 0.0 ps -a -o pid,pmem,cmd,vsz,d 148912 148822 89
    10906 0.0 screen -dr 129744 129744 0
    16116 0.0 sudo -i 195524 195524 0
    16117 0.3 -zsh 156876 156876 0
  • RES – Resident Memory Size (KiB)

    The non-swapped physical memory a task is using.(一个任务使用的不可交换的物理内存大小。是一个进程正在使用的内存空间(堆、栈)。)

  • SHR – Shared Memory Size (KiB)

    The amount of shared memory available to a task, not all of which is typically resident. It simply reflects memory that could be potentially shared with other processes.(一个任务正在使用的共享内存大小,这个大小对该进程不是固定的,它只是简单的反应了可以被其他进程共享的内存大小。)

Page Walk

  • Virtual to Physical address translations are stored in page tables
  • These page table are stored in memory
  • Looking up these page tables is a processes called a Page Walk
  • Every memory access requires a Page Walk
  • Hardware assisted but it is still expensive
  • Typically, takes 10-100 CPU clock cycles
  • The obvious optimization is to cache the results

virtual_to_physical

一次虚拟内存地址到物理内存地址查找(page walk)太慢,所以引入TLB来缓存。

TLB - Translation look-aside buffer

  • The Translation Lookaside Buffer(TLB) is a small CPU cache of recently used virtual to physical address mappings.
  • TLB is to speed up virtual to physical address translations
  • CPU checks TLB first
    • if TLB hit, return address
    • if TLB miss, do a Page Walk and store translation in TLB
  • Using TLB, increases performance by as much as 15%
  • Look up takes 0.5-1 clock cycle
  • TLB is typically implemented as CAM
    • CAM(Content addressable memory,内容寻址存储器)
  • TLB cache has to be flushed on every context switch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@localhost ~]# x86info -c
x86info v1.25. Dave Jones 2001-2009
Feedback to <davej@redhat.com>.

Found 40 CPUsMP Configuration Table Header MISSING!

--------------------------------------------------------------------------
CPU #1
EFamily: 0 EModel: 4 Family: 6 Model: 79 Stepping: 1
CPU Model: Unknown model.
Processor name string: Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz
Type: 0 (Original OEM) Brand: 0 (Unsupported)
Number of cores per physical package=16
Number of logical processors per socket=32
Number of logical processors per core=2
APIC ID: 0x0 Package: 0 Core: 0 SMT ID 0
Cache info
TLB info
Data TLB: 4KB pages, 4-way associative, 64 entries # TLB 很小
64 byte prefetching.
Found unknown cache descriptors: 63 76 b5 c3 ff

Huge Page

操作系统默认的内存是以4KB分页的,而虚拟地址和内存地址需要转换,而这个转换要查表,CPU为了加速这个查表过程会内建TLB(Translation Lookaside Buffer)。显然,如果虚拟页越小,表里的条目数也就越多,而TLB大小是有限的,条目数越多TLB的Cache Miss也就会越高,所以如果我们能启用大内存页就能间接降低TLB Cache Miss。

Huge Page在内存中必须是连续的地址,所以通常在系统开机时指定内核参数直接分配。

1
2
3
4
5
6
7
8
9
[root@yadoom ~]# sysctl -w vm.nr_hugepages=128
vm.nr_hugepages = 128
[root@yadoom ~]# cat /proc/meminfo | grep Huge
AnonHugePages: 77824 kB
HugePages_Total: 128
HugePages_Free: 128
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB

huge_pages_tlb

Transparent HugePages(透明大页)

  • 什么是Transparent HugePages(透明大页)?

    简单的讲,对于内存占用较大的程序,可以通过开启HugePage来提升系统性能。但这里会有个要求,就是在编写程序时,代码里需要显示的对HugePage进行支持。

    而红帽企业版Linux为了减少程序开发的复杂性,并对HugePage进行支持,部署了Transparent HugePages。Transparent HugePages是一个使管理Huge Pages自动化的抽象层,实现方案为操作系统后台有一个叫做khugepaged的进程,它会一直扫描所有进程占用的内存,在可能的情况下会把4kPage交换为Huge Pages。

    为什么Transparent HugePages(透明大页)对系统的性能会产生影响?
    在khugepaged进行扫描进程占用内存,并将4kPage交换为Huge Pages的这个过程中,对于操作的内存的各种分配活动都需要各种内存锁,直接影响程序的内存访问性能。并且,这个过程对于应用是透明的,在应用层面不可控制,对于专门为4k page优化的程序来说,可能会造成随机的性能下降现象。

  • 怎么设置Transparent HugePages(透明大页)?

    1. 查看是否启用透明大页

      1
      2
      3
      [root@yadoom ~]# cat /sys/kernel/mm/transparent_hugepage/enabled 
      [always] madvise never
      使用命令查看时,如果输出结果为[always]表示透明大页启用了,[never]表示透明大页禁用。
2. 关闭透明大页

    
1
2
echo never > /sys/kernel/mm/transparent_hugepage/enabled 
echo never > /sys/kernel/mm/transparent_hugepage/defrag
  1. 启用透明大页

    1
    2
    echo always >  /sys/kernel/mm/transparent_hugepage/enabled 
    echo always > /sys/kernel/mm/transparent_hugepage/defrag
4. 设置开机关闭

    
1
2
3
4
5
[root@yadoom ~]# vim /etc/rc.local
if test -f /sys/kernel/mm/redhat_transparent_hugepage/enabled; then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi

问题:Transparent Huge Pages相关概念及对mysql的影响

Swap

内存回收和swap的关系,我们可以提出以下几个问题:

  1. 什么时候会进行内存回收呢?
  2. 哪些内存会可能被回收呢?
  3. 回收的过程中什么时候会进行交换呢?
  4. 具体怎么交换?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
vm.swappiness={0..100}:使用交换分区的倾向性, 默认60
overcommit_memory=2: 过量使用(0:启发式过量;1:总是过量;2:允许下述超出百分比)
overcommit_ratio=50:
可用虚存:swap+RAM*ratio
swap: 2G
RAM: 8G
可用虚存:memory=2G+8G*50%=6G

充分使用物理内存:
1、swap跟RAM一样大;
2、overcommit_memory=2, overcommit_ratio=100:swappiness=0;
memory: swap+ram
参考设置:
1、Batch compute(批处理计算):<= 4 * RAM
2、Database server:<= 1G
3、Application server:>= 0.5 * RAM

默认值:
[root@yadoom ~]# cat /proc/sys/vm/overcommit_memory
0
[root@yadoom ~]# cat /proc/sys/vm/swappiness
60
[root@yadoom ~]# cat /proc/sys/vm/overcommit_ratio
50

Swap Tuning

1
2
3
4
5
6
[root@localhost ~]# vmstat 1 3
procs -----------memory---------- ---swap-- ----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 260352448 34480 2212952 0 0 0 1 2 3 0 0 100 0 0
0 0 0 260352192 34480 2212956 0 0 0 0 124 177 0 0 100 0 0
0 0 0 260352192 34480 2212956 0 0 0 0 27 44 0 0 100 0 0
  • Memory
    • swpd: the amount of virtual memory used.
  • Swap

    • si: Amount of memory swapped in from disk (/s).
    • so: Amount of memory swapped to disk (/s).

      paging in and paging out frequently hurts performance. si and so are very important.

1
2
3
4
5
6
# 在每个磁盘上建立swap分区,并给与相同优先级
[root@localhost ~]# vim /etc/fstab
.....
/dev/sda1 swap swap pri=5 0 0
/dev/sdb1 swap swap pri=5 0 0
/dev/sdc1 swap swap pri=1 0 0 # 最慢的磁盘,swap最小的优先级

Buffer Cache and Page Cache

  • Buffer cache(Slab cache)
    used to cache file system meta data(dentries and inodes).跟文件无关的东西的缓存。
  • Page cache
    used to cache file system block data(file content).跟文件相关的东西的缓存。
1
2
3
4
5
6
[root@localhost ~]# sysctl -a |grep vfs_cache_pressure   # Buffer cache
vm.vfs_cache_pressure = 100
# 0: 不回收dentries和inodes;
# 1-99: 倾向于不回收;
# 100: 倾向性等于 page cache和swap cache;
# 100+: 倾向于回收;

Slab

在linux内核中会有许多小对象,这些对象构造销毁十分频繁,比如inode,dentry。这么这些对象如果每次构建的时候就向内存要一个页,而其实际大小可能只有几个字节,这样就非常浪费,为了解决这个问题就引入了一种新的机制来处理在同一页框中如何分配小存储器区。这就是我们要讨论的slab层。在讲述slab前,我想先铺垫一下有关内存页的概念,我们都知道在linux中内存都是以页为单位来进行管理的(通常为4KB),当内核需要内存就调用如:kmem_getpages这样的接口(底层调用__alloc_pages())。那么内核是如何管理页的分配的,这里linux使用了伙伴算法。slab也是向内核申请一个个页,然后再对这些页框做管理来达到分配小存储区的目的的。

  • What is slab

    A slab is a set of one or more contiguous pages of memory set aside by the slab allocator for an individual cache. This memory is further divided into equal segments the size of the object type that the cache is managing.(Slab是一种内存分配器,通过将内存划分不同大小的空间分配给对象使用来进行缓存管理,应用于内核对象的缓存。)

  • 作用(提升cpu访问内存小对象的效率)

    • Slab对小对象进行分配,不用为每个小对象分配一个页,节省了空间。
    • 内核中一些小对象创建析构很频繁,Slab对这些小对象做缓存,可以重复利用一些相同的对象,减少内存分配次数。

Anonymous pages

  • Anonymous pages can be another large consumer of data
  • Are not accociated with a file, but instead contain
    • Program data - arrays, heap allocations, etc
    • Anonymous memory regions
    • Dirty memory mapped process private pages
    • IPC shared memory region pages
  • Anonymous pages are eligible for swap(Swap分区可以将不活跃的页交换到硬盘中,交换之后页将被释放。)
  • Anonymous pages = RSS - Shared

Memory Page Status

  • Free
    Page is available for immediate allocation.
  • Inactive Clean
    Page content has been written to disk, or has not changed since being read from disk. Page is available for allocation.
  • Inactive Dirty
    Page not in use, and page content has been modified but not written back to disk.
  • Active
    Page is in use by a process

Dirty Page

因为硬盘的读写速度远赶不上内存的速度,系统就把读写比较频繁的数据事先放到内存中,以提高读写速度,这就叫高速缓存,linux是以页作为高速缓存的单位,当进程修改了高速缓存里的数据时,该页就被内核标记为脏页,内核将会在合适的时间把脏页的数据写到磁盘中去,以保持高速缓存中的数据和磁盘中的数据是一致的。

1
2
3
4
5
6
7
8
9
10
[root@yadoom ~]# sysctl -a | grep dirty
vm.dirty_background_ratio = 10
vm.dirty_background_bytes = 0
vm.dirty_ratio = 20
vm.dirty_bytes = 0
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000

[root@yadoom ~]# sysctl -a | grep pdflush
vm.nr_pdflush_threads = 0
  • vm.dirty_expire_centisecs

    默认是3000(单位是1/100秒)。这个值表示page cache中的数据多久之后被标记为脏数据。只有标记为脏的数据在下一个周期到来时pdflush才会刷入到磁盘,这样就意味着用户写的数据在30秒之后才有可能被刷入磁盘,在这期间断电都是会丢数据的。

  • vm.dirty_writeback_centisecs

    默认一般是500(单位是1/100秒)。这个参数表示5s的时间pdflush就会被唤起去刷新脏数据。建议用户使用默认值。

  • vm.dirty_background_ratio(default 10)

    这个参数指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如5%)就会触发pdflush/flush/kdmflush等后台回写进程运行,将一定缓存的脏页异步地刷入外存;

  • vm.dirty_ratio(default 20)

    这个参数则指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如10%),系统不得不开始处理缓存脏页(因为此时脏页数量已经比较多,为了避免数据丢失需要将一定脏页刷入外存);在此过程中很多应用进程可能会因为系统转而处理文件IO而阻塞。

    之前一直错误的以为dirty_ratio的触发条件不可能达到,因为每次肯定会先达到vm.dirty_background_ratio的条件,后来才知道自己理解错了。确实是先达到vm.dirty_background_ratio的条件然后触发flush进程进行异步的回写操作,但是这一过程中应用进程仍然可以进行写操作,如果多个应用进程写入的量大于flush进程刷出的量那自然会达到vm.dirty_ratio这个参数所设定的坎,此时操作系统会转入同步地处理脏页的过程,阻塞应用进程。

  • vm.nr_pdflush_threads
    pdflush是linux系统后台运行的一个线程,这个进程负责把page cahce中的dirty状态的数据定期的输入磁盘。

    /proc/sys/vm/nr_pdflush_threads查看当前系统运行pdflush数量。当一段时间(一般是1s)没有任何的pdflush处于工作状态,系统会remove一个pdflush线程。pdflush最大和最小的数量是有配置的,但这些配置一般很少修改。

  • drop_caches(干净页的回收,缓存清理)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@yadoom ~]# cat /proc/sys/vm/drop_caches
    0
    [root@yadoom ~]# sync #先将缓存写入磁盘
    [root@yadoom ~]# echo 1 /proc/sys/vm/drop_caches #释放所有页缓冲内存
    [root@yadoom ~]# echo 2 /proc/sys/vm/drop_caches #释放未使用的slab缓冲内存
    [root@yadoom ~]# echo 3 /proc/sys/vm/drop_caches #释放所有页缓冲和slab缓冲内存
    备注:
    slab缓存详解(一)http://blog.chinaunix.net/uid-27102327-id-3268687.html
    slab缓存详解(二)http://blog.chinaunix.net/uid-27102327-id-3268711.html
    http://blog.csdn.net/hs794502825/article/details/7981524

OOM Kill

1
2
3
4
5
6
7
8
9
10
11
12
[root@yadoom ~]# cat /proc/sys/vm/panic_on_oom     # 0:on, 1:off
0
[root@yadoom ~]# echo 1 /proc/sys/vm/panic_on_oom # 关闭oom kill,不推荐
注意:由调整的进程衍生的进程将继承该进程的 oom_score。例如:如果 sshd 进程不受 oom _killer 功能影响,所有由 SSH 会话产生的进程都将不受其影响。

当内存耗尽时,系统使用oom kill杀死大oom_score(-16~15,2的平方)的进程。oom_score得分由oom_adj得来。
减小oom-adj值,避免被系统杀死:
[root@yadoom ~]# echo -17 > /proc/$(pidof sshd)/oom_adj

-17:避免oom_killer杀死自己
-16~15:帮助计算oom_score
16:预留的最低级别,一般对于缓存的进程才有可能设置成这个级别

有时free查看还有充足的内存,但还是会触发OOM,是因为该进程可能占用了特殊的内存地址空间。(‘Lower’ memory zone like DMA, DMA32)

min_free_kbytes

  • /proc/sys/vm/min_free_kbytes
    强制Linux VM最低保留多少空闲内存(Kbytes)

内存管理从三个层次管理内存,分别是node, zone ,page。64位的x86物理机内存从高地址到低地址分为: Normal DMA32 DMA

1
2
3
4
5
[root@yadoom ~]# grep Node /proc/zoneinfo 
Node 0, zone DMA
Node 0, zone DMA32
Node 0, zone Normal
Node 1, zone Normal

每个zone都有自己的min low high,如下,但是单位是page。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[root@yadoom ~]# grep "Node 0, zone" -A10 /proc/zoneinfo 
Node 0, zone DMA
pages free 3934
min 3
low 3
high 4
scanned 0
spanned 4095
present 3835
nr_free_pages 3934
nr_inactive_anon 0
nr_active_anon 0
--
Node 0, zone DMA32
pages free 571977
min 749
low 936
high 1123
scanned 0
spanned 1044480
present 756520
nr_free_pages 571977
nr_inactive_anon 0
nr_active_anon 0
--
Node 0, zone Normal
pages free 4737209
min 9478
low 11847
high 14217
scanned 0
spanned 9699328
present 9566720
nr_free_pages 4737209
nr_inactive_anon 166
nr_active_anon 3973945

上面可知:low = 5/4 min、high = 3/2 min。

min 和 low的区别:

  1. min下的内存是保留给内核使用的;当到达min,会触发内存的direct reclaim
  2. low水位比min高一些,当内存可用量小于low的时候,会触发 kswapd reclaim。当kswapd慢慢的将内存 回收到high水位,就开始继续睡眠
  • /proc/sys/vm/extra_free_kbytes
1
2
3
[root@yadoom ~]# sysctl  -a | grep free
vm.min_free_kbytes = 90112
vm.extra_free_kbytes = 0

意义:low = min_free_kbytes*5/4 + extra_free_kbytes

  • 总结

调整该内存的内核参数的时候!调大的风险远大于调小的风险,会导致频繁的触发内存回收!如果有人想将vm.min_free_kbytes 调大,千万要注意当前的Free,一旦超过Free内存,会立刻触发direct reclaim。

进程间通信(SysV IPC)

  • Types of IPC
    • Semaphores(信号量)
    • Message queues(消息队列)
    • Shared memory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[root@kvm-2 ~]# ipcs 

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x6c0006e7 0 zabbix 600 657056 6

------ Semaphore Arrays --------
key semid owner perms nsems
0x00000000 0 root 600 1
0x00000000 65537 root 600 1
0x7a0006e7 98306 zabbix 600 13

------ Message Queues --------
key msqid owner perms used-bytes messages

[root@kvm-2 ~]# ipcs -l # IPC resource limits

------ Shared Memory Limits --------
max number of segments = 4096 # SHMMNI
max seg size (kbytes) = 49291832 # SHMMAX
max total shared memory (kbytes) = 25165824 # SHMALL
min seg size (bytes) = 1

------ Semaphore Limits --------
max number of arrays = 128 # SEMMNI
max semaphores per array = 250 # SEMMSL
max semaphores system wide = 32000 # SEMMNS
max ops per semop call = 100 # SEMOPM
semaphore max value = 32767

------ Messages: Limits --------
max queues system wide = 32768 # MSGMNI
max size of message (bytes) = 65536 # MSGMAX
default max size of queue (bytes) = 65536 # MSGMNB
  • Tune Semaphores

    • 1st, the maximum number of semaphores per semaphore array, default 250.
    • 2st, the maximum number of semaphores allowed sysetm-wide, default 32000.
    • 3st, the maximum number of semaphores of allowed operations per semaphore system call, default 32.
    • 4st, the maximum number of semaphore arrays, default 128.
    • so, 250 * 128 <= 32000

      1
      2
      [root@kvm-2 ~]# sysctl -a | grep kernel.sem
      kernel.sem = 250 32000 32 128
  • Tune Message Queues

    • kernel.msgmnb
      The maximum number of bytes in a single message queue, default 65535.
    • kernel.msgmni
      The maximum number of message queue, default ?.
    • kernel.msgmax
      The maximum size of a message that can be passwd between processes, default 65535.

      1
      2
      3
      4
      [root@kvm-2 ~]# sysctl -a | grep kernel.msg
      kernel.msgmax = 65536 # 限制进程可以发送消息的最大字节数
      kernel.msgmni = 32768 # 最大消息队列数
      kernel.msgmnb = 65536 # 一个消息队列中最大的字节数
  • Tune

    • kernel.shmmni
      The maximum number of shared memory segments system-wide, default 4096.
    • kernel.shmmax
      The maximum size of a shared memory segment that can be created, default 68719476736(64G).
    • kernel.shmall
      The total amount of shared memory, in pages, that can be used at one time on the system. default

      1
      2
      3
      4
      [root@yadoom ~]# sysctl -a | grep kernel.shm
      kernel.shmmax = 68719476736
      kernel.shmall = 4294967296 # 单位page,等于 4294967296(4g)*4096 byte
      kernel.shmmni = 4096

延展阅读

File System Tuning

Mount Options

  • Barriers (barrier)
    • 由于磁盘设备自带内部缓存,以便重新调整批量数据的写操作顺序,优化写入性能,因此文件系统必须在日志数据写入磁盘之后才能写commit记录,若commit 记录写入在先,而日志有可能损坏,那么就会影响数据完整性。Ext4默认启用barrier,只有当barrier之前的数据全部写入磁盘,才能写 barrier之后的数据。
  • Access Time (noatime)
    • In most cases, however, atime
      is not a large overhead due to the default relative atime (or relatime) behavior in the RHEL 6 kernel.
    • The relatime behavior only updates atime if the previous atime is older
      than the modification time (mtime) or status change time (ctime).

File System

  • EXT4

    • 内节点表初始化

      对于超大文件系统,mkfs.ext4 进程要花很长时间初始化文件系统中到所有内节点表。可使用 -Elazy_itable_init=1 选项延迟这个进程。如果使用这个选项,内核进程将在挂载文件系统后继续初始化
      该文件它。可使用 mount 命令的 -o init_itable=n 选项控制发生初始化到比例,其中执行这个后台初始化的时间约为 1/n。n 的默认值为 10。

    • Auto-fsync 行为

      因为在重命名、截取或者重新写入某个现有文件后,有些应用程序不总是可以正确执行 fsync(),在重命名和截取操作后,ext4 默认自动同步文件。这个行为与原有到 ext3 文件系统行为大致相同。但 fsync()
      操作可能会很耗时,因此如果不需要这个自动行为,请在 m ount 命令后使用 -o noauto_da_alloc 选项禁用它。这意味着该程序必须明确使用 fsync() 以保证数据一致。

    • 日志 I/O 优先权

      默认情况下,日志注释 I/O 比普通 I/O 的优先权稍高。这个优先权可使用 mount 命令的journal_ioprio=n 选项控制。默认值为 3。有效值范围为 0 -7,其中 0 时最高优先权 I /O。

  • XFS(large file system)

Network Tuning

Tune Network latency

  • net.ipv4.tcp_low_latency
    • optimizes for low latency
    • optimizes for throughput(default)
      默认的RHEL为高吞吐量设计。

TCP/UDP Total Maximum Buffers

  • When receiving and network packets, there are buffers(queue length)
  • Kernel adjusts the size of these buffers automatically
  • System wide maximum buffers for TCP/UDP connections, usually no need to tune, set by kernel during boot, near the size of system memory
    • net.ipv4.tcp_mem(pages)
    • net.ipv4.udp_mem(pages)
  • Each connection creates a buffer

Tune UDP Socket Buffer

  • Tune the minimum socket buffers for UDP connection
    • net.ipv4.udp_rmem_min(bytes)
    • net.ipv4.udp_wmem_min(bytes)
  • Tune the default socket buffers for core networking, include udp connection
    • net.core.rmem_default(bytes)
    • net.core.wmem_default(bytes)
  • Tune the maximum socket buffers for core networking, include udp connection
    • net.core.rmem_max(bytes)
    • net.core.wmem_max(bytes)
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# sysctl -a | grep net.ipv4.udp
net.ipv4.udp_mem = 24786432 33048576 49572864
net.ipv4.udp_rmem_min = 4096
net.ipv4.udp_wmem_min = 4096
[root@localhost ~]# sysctl -a | grep net.core | grep mem
net.core.wmem_max = 124928
net.core.rmem_max = 124928
net.core.wmem_default = 124928
net.core.rmem_default = 124928
# 由上可知 mem_default 等于 mem_max,表示已调节为最大吞吐量,缺点是需要占用大量内存。

Tune TCP Socket Buffer

  • First, tune buffers of total networking(like UDP)
    • net.core.rmem_max(bytes)
    • net.core.wmem_max(bytes)
  • Then tune buffers of TCP specific networking

    • net.ipv4.tcp_rmem(bytes)
    • net.ipv4.tcp_wmem(bytes)

      1
      2
      net.ipv4.tcp_wmem = 4096        16384   4194304
      net.ipv4.tcp_rmem = 4096 87380 4194304
      • min: minimum receive/send buffer for a tcp connection
      • default: default buffer size, usually half of max buffer size
      • max: maximum receive/send buffer for a tcp connection
  • Total networking buffers >= TCP buffers

How much buffer to set?

  • Set buffer too large will hurt network speed and latency for connections of small amounts data(HTTP/SSH)
  • Set buffer too small will cause system dropping network packets
  • To calculate buffer size for maximum throughput of a BDP(Bandwidth Delay Product,时延带宽积) connection.(时延带宽积代表发送的第一个比特即将达到终点时、发送端就已经发出了多少个比特。因此时延带宽积又称为以比特为单位的链路长度。)
    • BDP = Bandwidth * Delay
    • Example: 1 Mbits/s/8 * 2s = 262144 Bytes = 256 KiB
    • when BDP goes above 64 KiB, tcp connections will use window scalling(滑动窗口) by default to enable full use of BDP buffer, good for sending large files over slow networks

Ethernet Bonding

  • Bonding mode
    • balance-rr,0: provides fault tolerance and load balancing(more like app level compared to mode 4)
    • active-backup,1: provides fault tolerance
    • 802.3ad,4: Dynamic Link Aggregation, must configure switch also, default work on layer 2, can be set work on layer 2 and 3 with xmit_hash_policy=layer2+3
    • Bonding (Port Trunking)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
[root@localhost network-scripts]# cat ifcfg-em1
......
DEVICE=em1
MASTER=bond0
SLAVE=yes

[root@localhost network-scripts]# cat ifcfg-em2
......
DEVICE=em2
MASTER=bond0
SLAVE=yes

[root@localhost network-scripts]# more ifcfg-bond0
DEVICE=bond0
TYPE=Bond
NAME=bond0
BONDING_MASTER=yes
BOOTPROTO=static
USERCTL=no
ONBOOT=yes
IPADDR=172.20.0.2
PREFIX=24
GATEWAY=172.20.0.1
BONDING_OPTS="mode=1 miimon=100"
# BONDING_OPTS="mode=802.3ad xmit_hash_policy=layer2+3"

[root@localhost network-scripts]# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: fault-tolerance (active-backup)
Primary Slave: None
Currently Active Slave: em1
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0

Slave Interface: em1
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: d0:94:66:24:77:f4
Slave queue ID: 0

Slave Interface: em2
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: d0:94:66:24:77:f6
Slave queue ID: 0

Protocal Overheads

  • When data is being sent over network, kernel forges packets, a typical TCP/IP packet head includes: Ethernet header, IP header and TCP header.
    • TCP connection uses 52 bytes for protocol headers, with a default MTU of 1500 bytes, that’s (52/1500) = 3.5% overhead
    • UDP connection with 28 bytes for protocol headers, that’s (28/1500) = 1.9% overhead

Jumbo Frames

  • To increase MTU can reduce these overhead
  • MTU bigger that 1500 is called Jumbo Frames
  • Every piece of networking equipment on the network must support Jumbo frames
    Nics, Switches, Routers, etc.
  • Official maximum size of a Jumbo frame is 9000 bytes
    (52/ 9000) = 0.58% overhead, compared to 3.5% before

    1
    2
    3
    [root@localhost network-scripts]# cat ifcfg-em1
    ......
    MTU=9000

其他

1
2
3
tcp_max_tw_buckets: 只允许调大
tw:保存timewait的连接个数
established --> tw
  • txqueuelen

    表示传送数据的缓冲区的最大长度。假设最大并发用户数为u,单次向用户推送数据占用的IP包为p个,则瞬间推送的IP包数为up,网卡发送队列长度需足够大以容纳这么多包数。考虑到一定的余量,建议txqueuelen设为u p 1.2,如果推送数据较小,则p = 1,txqueuelen = u 1.2。

    1
    2
    [root@yadoom ~]# ifconfig em1 | grep txqueuelen
    collisions:0 txqueuelen:1000
  • 网卡接受发送队列

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 看网卡的接受发送队列长度,intel网卡缺省256,可以设置到 4096
    [root@yadoom ~]# ethtool -g em1
    Ring parameters for em1:
    Pre-set maximums:
    RX: 2047
    RX Mini: 0
    RX Jumbo: 0
    TX: 511 # 队列长度
    Current hardware settings:
    RX: 200
    RX Mini: 0
    RX Jumbo: 0
    TX: 511

    # 设置网卡的接受发送队列
    # ethtool -G em1 rx N

案例

  • Too much ARP cache?

    • ip neighbor list

      1
      2
      3
      net.ipv4.neigh.default.gc_thresh1 = 128
      net.ipv4.neigh.default.gc_thresh2 = 512
      net.ipv4.neigh.default.gc_thresh3 = 1024
    • ip neigh flush dev ethN

内核参数

  • net.ipv4.tcp_tw_recycle

不要在linux上启用net.ipv4.tcp_tw_recycle参数

cgroup

  • Enable cgroup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@localhost ~]# yum install gcc libcap-devel libcgroup-devel -y
[root@localhost ~]# ls /etc/cgconfig.conf # cgroup主配置文件
[root@localhost ~]# /etc/init.d/cgconfig start
Starting cgconfig service: [ OK ]
[root@localhost ~]#
[root@localhost ~]# ls -l /cgroup/
total 0
drwxr-xr-x 2 root root 0 Dec 6 01:06 blkio
drwxr-xr-x 2 root root 0 Dec 6 01:06 cpu
drwxr-xr-x 2 root root 0 Dec 6 01:06 cpuacct
drwxr-xr-x 2 root root 0 Dec 6 01:06 cpuset
drwxr-xr-x 2 root root 0 Dec 6 01:06 devices
drwxr-xr-x 2 root root 0 Dec 6 01:06 freezer
drwxr-xr-x 2 root root 0 Dec 6 01:06 memory
drwxr-xr-x 2 root root 0 Dec 6 01:06 net_cls
  • Control cgroups Services
    • cgconfig
      • mount controllers
      • create cgroups
      • enables cgroup configure
    • cgred
      • assign process of specific users to cgroup
      • assign specific processes to cgroup
1
2
3
4
5
6
7
8
9
[root@localhost ~]# lssubsys -m
cpuset /cgroup/cpuset
cpu /cgroup/cpu
cpuacct /cgroup/cpuacct
memory /cgroup/memory
devices /cgroup/devices
freezer /cgroup/freezer
net_cls /cgroup/net_cls
blkio /cgroup/blkio

To Control CPU Usage(案例,CPU使用控制)

1. Create cgroups under cpu controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@localhost ~]# vim /etc/cgconfig.d/mycpu.conf
group lesscpu {
cpu {
}
}
group morecpu {
cpu {
}
}
[root@localhost cgconfig.d]# /etc/init.d/cgconfig reload
Stopping cgconfig service: [ OK ]
Starting cgconfig service: [ OK ]
[root@localhost cgconfig.d]# ls /cgroup/cpu/lesscpu/
cgroup.event_control cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release
cgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks
[root@localhost cgconfig.d]# ls /cgroup/cpu/morecpu/
cgroup.event_control cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release
cgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks

# 临时调整
[root@localhost cgconfig.d]# cgcreate -g cpu:/lesscpu
[root@localhost cgconfig.d]# cgcreate -g cpu:/morecpu
或者
[root@localhost cgconfig.d]# mkdir /cgroup/cpu/{less,more}
2. Configure priorities or limits
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@localhost ~]# vim /etc/cgconfig.d/mycpu.conf
group lesscpu {
cpu {
cpu.shares=100;
}
}
group morecpu {
cpu {
cpu.shares=200;
}
[root@localhost cgconfig.d]# more /cgroup/cpu/lesscpu/cpu.shares
100
[root@localhost cgconfig.d]# more /cgroup/cpu/morecpu/cpu.shares
200

# 临时调整,重载后失效
[root@localhost cgconfig.d]# cgset -r cpu.shares=100 lesscpu
[root@localhost cgconfig.d]# cgset -r cpu.shares=200 morecpu
3. Assign processes to cgroups
1
2
3
4
5
6
7
8
# 需要把其他CPU下线,只剩一核的情况下测试
[root@localhost cgconfig.d]# cgexec -g cpu:lesscpu time dd if=/dev/zero of=/dev/null bs=1M count=200000
200000+0 records in
200000+0 records out
209715200000 bytes (210 GB) copied, 11.4672 s, 18.3 GB/s
0.01user 11.43system 0:11.46elapsed 99%CPU (0avgtext+0avgdata 1848maxresident)k
0inputs+0outputs (0major+491minor)pagefaults 0swaps
[root@localhost cgconfig.d]# cgexec -g cpu:morecpu time dd if=/dev/zero of=/dev/null bs=1M count=200000

To Control Memory Usage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@localhost ~]# vim /etc/cgconfig.d/mymem.conf
group poormem {
memory {
# Physical memory limit, 256M, must be first set
memory.limit_in_bytes=268435456;
# Total memory limit, 512M, Physical Memory + Swap
memory.memsw.limit_in_bytes=536870912;
}
}
[root@localhost cgconfig.d]# /etc/init.d/cgconfig reload
Stopping cgconfig service: [ OK ]
Starting cgconfig service: [ OK ]
[root@localhost cgconfig.d]# cat /cgroup/memory/poormem/memory.limit_in_bytes
268435456
[root@localhost cgconfig.d]# cat /cgroup/memory/poormem/memory.memsw.limit_in_bytes
268435456

[root@localhost cgconfig.d]# cgexec -g memory:poormem dd if=/dev/zero of=/dev/null bs=1M count=300
# 该命令会占用256M物理内存,以及300-256=44M Swap内存。

To Control Disk I/O Usage

  • Create cgroup under blkio controller
  • Configure blkio priorities and usage limit
  • Assign processes to cgroups

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    [root@localhost ~]# vim /etc/cgconfig.d/myio.conf
    group lowio {
    blkio {
    blkio.weight=100; # blkio.weight works under cfq scheduler
    }
    }
    group highio {
    blkio {
    blkio.weight=200; # blkio.weight works under cfq scheduler
    }
    }
    group ddio {
    blkio {
    blkio.throttle.read_bps_device="8:0 1000000"
    # 针对主号,从号“8:0”的磁盘设备限制I/O吞吐量
    }
    }
    # 上面“8:0”(主号,从号)由下面的命令查看而来。
    [root@localhost ~]# ls -l /dev/sda
    brw-rw---- 1 root disk 8, 0 Dec 6 03:25 /dev/sda

    [root@localhost cgconfig.d]# /etc/init.d/cgconfig reload
    Stopping cgconfig service: [ OK ]
    Starting cgconfig service: [ OK ]

    [root@localhost ~]# cat /sys/block/sda/queue/scheduler
    noop anticipatory deadline [cfq]
    [root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches
    [root@localhost ~]#
    [root@localhost ~]# ls -lh /tmp/bigfile*
    -rw-r--r-- 1 root root 1000M Dec 6 03:52 /tmp/bigfile1
    -rw-r--r-- 1 root root 1000M Dec 6 03:52 /tmp/bigfile2
    [root@localhost tmp]# cgexec -g blkio:lowio time cat ./bigfile1 > /dev/null
    [root@localhost tmp]# cgexec -g blkio:highio time cat ./bigfile2 > /dev/null

Using cgred

1
2
3
4
5
[root@localhost ~]# vim /etc/cgrules.conf 
#<user> <controllers> <destination>
john:* blkio ddio/
*:dd blkio ddio/
[root@localhost ~]# /etc/init.d/cgred reload

To Freeze Certain Processes

1
2
3
4
5
6
7
8
9
[root@localhost ~]# vim /etc/cgconfig.d/freeze.conf
group stopit {
freezer {
}
}
[root@localhost ~]# /etc/init.d/cgconfig reload
[root@localhost ~]# echo #pid > /cgroup/freezer/stopit/tasks # 绑定进程和freezer控制器
[root@localhost ~]# echo FROZEN > /cgroup/freezer/stopit/freezer.state # 冻结该进程
[root@localhost ~]# echo THAWED > /cgroup/freezer/stopit/freezer.state # 解冻

Command

strace & ltrace

  • strace: kernerl space(system call)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    [root@localhost ~]# strace -e trace=network ping -c 1 127.0.0.1 
    socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
    socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
    connect(4, {sa_family=AF_INET, sin_port=htons(1025), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
    getsockname(4, {sa_family=AF_INET, sin_port=htons(55365), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
    setsockopt(3, SOL_RAW, ICMP_FILTER, ~(ICMP_ECHOREPLY|ICMP_DEST_UNREACH|ICMP_SOURCE_QUENCH|ICMP_REDIRECT|ICMP_TIME_EXCEEDED|ICMP_PARAMETERPROB), 4) = 0
    setsockopt(3, SOL_IP, IP_RECVERR, [1], 4) = 0
    setsockopt(3, SOL_SOCKET, SO_SNDBUF, [324], 4) = 0
    setsockopt(3, SOL_SOCKET, SO_RCVBUF, [65536], 4) = 0
    getsockopt(3, SOL_SOCKET, SO_RCVBUF, [131072], [4]) = 0
    PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
    setsockopt(3, SOL_SOCKET, SO_TIMESTAMP, [1], 4) = 0
    setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
    setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
    sendmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("127.0.0.1")}, msg_iov(1)=[{"\10\0\224B+\23\0\1\31<\10\\\0\0\0\0V>\2\0\0\0\0\0\20\21\22\23\24\25\26\27"..., 64}], msg_controllen=0, msg_flags=0}, 0) = 64
    recvmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("127.0.0.1")}, msg_iov(1)=[{"E\0\0TQ\253\0\0@\1*\374\177\0\0\1\177\0\0\1\0\0\234B+\23\0\1\31<\10\\"..., 192}], msg_controllen=32, {cmsg_len=32, cmsg_level=SOL_SOCKET, cmsg_type=0x1d /* SCM_??? */, ...}, msg_flags=0}, 0) = 84
    64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.035 ms

    --- 127.0.0.1 ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 0.035/0.035/0.035/0.000 ms
    +++ exited with 0 +++

    [root@localhost ~]# strace -e trace=file ls /
    execve("/bin/ls", ["ls", "/"], [/* 21 vars */]) = 0
    access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
    open("/etc/ld.so.cache", O_RDONLY) = 3
    open("/lib64/libselinux.so.1", O_RDONLY) = 3
    open("/lib64/librt.so.1", O_RDONLY) = 3
    open("/lib64/libcap.so.2", O_RDONLY) = 3
    open("/lib64/libacl.so.1", O_RDONLY) = 3
    open("/lib64/libc.so.6", O_RDONLY) = 3
    open("/lib64/libdl.so.2", O_RDONLY) = 3
    open("/lib64/libpthread.so.0", O_RDONLY) = 3
    open("/lib64/libattr.so.1", O_RDONLY) = 3
    statfs("/selinux", {f_type="EXT2_SUPER_MAGIC", f_bsize=4096, f_blocks=1297385108, f_bfree=1296583382, f_bavail=1230678333, f_files=329531392, f_ffree=329482788, f_fsid={-525262460, 379377246}, f_namelen=255, f_frsize=4096}) = 0
    open("/proc/filesystems", O_RDONLY) = 3
    open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
    stat("/", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0
    open("/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
    bin boot cgroup dev etc home lib lib64 lost+found media mnt opt proc root sbin selinux srv sys tmp usr var
    +++ exited with 0 +++
  • ltrace: user space(library function call)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    [root@localhost ~]# ltrace date
    (0, 0, 0, 0x7f6770d11bc8, 88) = 0x30b3a22160
    __libc_start_main(0x401ec0, 1, 0x7ffff9ae0dc8, 0x408f30, 0x408f20 <unfinished ...>
    strrchr("date", '/') = NULL
    setlocale(6, "") = "en_US.UTF-8"
    bindtextdomain("coreutils", "/usr/share/locale") = "/usr/share/locale"
    textdomain("coreutils") = "coreutils"
    __cxa_atexit(0x4057a0, 0, 0, 0x736c6974756572, 0x30b3f8e188) = 0
    getopt_long(1, 0x7ffff9ae0dc8, "d:f:I::r:Rs:u", 0x60c1a0, NULL) = -1
    nl_langinfo(131180, 0x7ffff9ae0dc8, 0x30b3f8e9ec, 0x30b3f8e9e4, 0) = 0x7f676affd425
    clock_gettime(0, 0x7ffff9ae0c90, 0x1a06440, 0x30b3f8e9e4, 0) = 0
    localtime(0x7ffff9ae0b80) = 0x30b3f93440
    strftime("", 140082153508067, NULL, 0x7ffff9ae0b23) = 4
    fwrite("Wed", 3, 1, 0x30b3f8f040) = 1
    fputc(' ', 0x30b3f8f040) = 32
    strftime("", 140082153508184, NULL, 0x7ffff9ae0b23) = 4
    fwrite("Dec", 3, 1, 0x30b3f8f040) = 1
    fputc(' ', 0x30b3f8f040) = 32
    fputc(' ', 0x30b3f8f040) = 32
    fwrite("5", 1, 1, 0x30b3f8f040) = 1
    fputc(' ', 0x30b3f8f040) = 32
    fwrite("21", 2, 1, 0x30b3f8f040) = 1
    fputc(':', 0x30b3f8f040) = 58
    fwrite("25", 2, 1, 0x30b3f8f040) = 1
    fputc(':', 0x30b3f8f040) = 58
    fwrite("49", 2, 1, 0x30b3f8f040) = 1
    fputc(' ', 0x30b3f8f040) = 32
    strlen("CST") = 3
    fwrite("CST", 3, 1, 0x30b3f8f040) = 1
    fputc(' ', 0x30b3f8f040) = 32
    fwrite("2018", 4, 1, 0x30b3f8f040) = 1
    exit(0 <unfinished ...>
    __fpending(0x30b3f8f040, 0, 0x30b3f8fbd0, 0x30b3f8fbd0, 4) = 29
    fclose(0x30b3f8f040) = 0
    Wed Dec 5 21:25:49 CST 2018
    __fpending(0x30b3f8f120, 0, 0x30b3f906b0, 0, 0x7f6770d10700) = 0
    fclose(0x30b3f8f120) = 0
    +++ exited (status 0) +++

systemtap

Powerful tracing system to profile kernel space and user space code.

结尾

  • 性能观测工具

linux_observability_tools

  • 性能测评工具

linux_benchmarking_tools

  • 性能调优工具

linux_tuning_tools

  • sar命令

linux_observability_sar

linux_perf_tools_full

附录

http://honglus.blogspot.com/

kai yu wechat
喜欢我~
0%