# Cpu
---
# Mem
---
## 常见的内核参数
```bash
# 关闭swap
vm.swappiness = 0
# vm.watermark_scale_factor 用于动态调整内存水位线(watermarks)的缩放比例。分为三个关键阈值(min、low、high),用于管理物理内存的回收:
# - min: 系统保留的最低空闲内存,触发Direct Reclaim, 会加剧磁盘 IO 压力。
# - low: 当空闲内存低于此值时,内核启动后台回收(kswapd)。
# - high: 当空闲内存达到此值时,停止后台回收。
# 决定min水位线,low = min * 1.5,high = min * 3, 有效范围:0 到 1000(对应 0% 到 10% 的总内存比例)
# 在/proc/zoneinfo中有min、low、high的对应值
vm.watermark_scale_factor = 500
# 可以通过"/proc/vmstat"中的"pageoutrun"和"allocstall"来查看,两者分别代表了kswapd和direct reclaim启动的次数。
(base) [root@zzzz ~]# grep -E "pageoutrun|allocstall" /proc/vmstat
allocstall_dma 0
allocstall_dma32 0
allocstall_normal 28729166
allocstall_movable 10533
pageoutrun 6241380
# 当系统经历高内存压力(如直接内存回收)后,内核会临时提高内存区域(zone)的 min、low、high 水位值。vm.watermark_boost_factor 决定了提升的幅度。
# 预防内存压力:通过更早触发内存回收(kswapd),避免频繁进入直接回收或 OOM(Out-Of-Memory)状态,提高系统稳定性。
vm.watermark_boost_factor = 15000
# 用于查看 物理内存中各个 zone 的空闲页分布的重要命令,尤其在内存碎片化、内存分配失败(如 order 高的分配失败)时非常有用。
# Node: NUMA 节点号
# zone: 内存区域(DMA、DMA32、Normal、Movable 等)
# 接下来的 11 个数字: 分别表示 order=0 到 order=10 的空闲页块数量
# order=0 表示 1 页(4KB), order=1 表示 2 页(8KB)......, order=10 表示 1024 页(4MB)
# 每一个数字表示当前有多少个对应大小的 连续物理内存块 可分配
# 多用于判断内存碎片化, 比如: order=0 有很多,高 order 的数量是 0
(base) [root@zzzz ~]# cat /proc/buddyinfo
Node 0, zone DMA 1 0 0 0 0 0 0 0 1 1 3
Node 0, zone DMA32 6 8 9 6 7 5 3 5 2 5 455
Node 0, zone Normal 13630 18308 90520 123480 213137 198410 152556 107402 64820 56306 0
Node 1, zone Normal 5156 5187 47534 51478 237809 232256 179879 126473 74265 44027 184
# 手动触发内存压缩,将分散的空闲页面整理成连续页面
# compact_memory 不会释放内存,只是重新整理空闲内存页的位置。
echo 1 > /proc/sys/vm/compact_memory
# 后台自动压缩,开启持续性压缩行为
# 1-100:数值越大越“积极压缩”
vm.compaction_proactiveness = 50
# 设置触发后台脏页回写的绝对内存阈值(字节单位)
# 0:禁用绝对值模式,改用 dirty_background_ratio(比例模式)。
# ≥1:指定具体字节数(如 1048576 = 1MB)。
vm.dirty_background_bytes = 0
# 当系统内存中脏页占比 ≥ 设定比例时,触发 异步后台回写(不阻塞应用)
# 配置范围:0 ~ 100(百分比)
# 低值(如 5):频繁小批量回写,减少数据丢失风险,但增加I/O负载
# 高值(如 20):延迟回写,提升写入吞吐,但内存不足时可能突发高I/O
vm.dirty_background_ratio = 10
# 设置触发同步脏页回写的绝对内存阈值(字节单位)
# 0:禁用绝对值模式,改用 dirty_ratio(比例模式)
# ≥1:指定具体字节数
vm.dirty_bytes = 0
# 脏页在内存中驻留的最长时间(单位:1/100秒),超时后强制回写
# 短时间(如 1000=10秒):频繁回写,减少数据丢失,但增加I/O压力
# 长时间(如 3000=30秒):适合批量写入场景(如日志服务器),但崩溃时可能丢失更多数据
vm.dirty_expire_centisecs = 3000
# 当系统内存中脏页占比 ≥ 设定比例时,触发 同步阻塞回写(应用写入被暂停)
# 低值(如 10):快速回写,减少阻塞,但限制写入吞吐
# 高值(如 30):允许更多脏页累积,提升突发写入性能,但可能导致应用卡顿
vm.dirty_ratio = 20
# 内核周期性唤醒回写线程的时间间隔(单位:1/100秒)
# 短间隔(如 100=1秒):实时回写,减少数据驻留时间,适合低延迟存储(如SSD)
# 长间隔(如 500=5秒):降低CPU开销,但可能延迟回写
vm.dirty_writeback_centisecs = 500
# 标记为“脏页”的最长保留时间(秒),超时后可能被优先回收
# 短时间(如 3600=1小时):加速回收长期未访问的脏页,节省内存
# 长时间(如 43200=12小时):减少频繁回收,适合内存充足且需要缓存持久化的场景
vm.dirtytime_expire_seconds = 43200
```

Linux中的内存回收 [一]: https://zhuanlan.zhihu.com/p/70964195
Linux中的内存回收[二]: https://zhuanlan.zhihu.com/p/72998605
Linux内存调节之zone watermark: https://zhuanlan.zhihu.com/p/73539328
内存相关的内核参数: https://www.cnblogs.com/arnoldlu/p/18782680
# Disk
---
# Network
---
## 网卡队列绑核
### 概念
网卡队列绑核(也称为 **中断亲和性设置** 或 **IRQ Affinity**)是一种优化服务器网络性能的技术,通过将**网卡的不同接收队列(RX Queues)绑定到特定的 CPU 核心**,减少 CPU 缓存失效、提升数据本地性,从而显著提高网络吞吐量并降低延迟
`只针对TCP网卡, RDMA网卡不用, RDMA网卡的处理不经过内核协议栈`
1. **多队列网卡**:现代高性能网卡(尤其是千兆、万兆及以上)通常支持多个硬件队列(通常称为接收侧缩放 - Receive Side Scaling, RSS)。当网卡收到数据包时,会根据数据包的元信息(如源/目的 IP、端口、协议等)通过哈希算法,将不同的数据流分配到不同的硬件队列中。这样做的核心目的是实现**并行处理**,避免单个队列成为瓶颈。
2. **中断(IRQ)**:当网卡的某个硬件队列收到数据包后,它需要通知操作系统内核来处理这些数据包。这种通知机制就是硬件中断(IRQ)。每个硬件队列通常对应一个独立的中断号(IRQ number)。
3. **中断处理与软中断**:当 CPU 收到硬件中断信号时,它会暂停当前工作,执行一个简短的**硬中断处理程序**(主要工作是确认中断、做一些必要标记)。硬中断处理程序通常会调度一个**软中断**(SoftIRQ,如 NET_RX_SOFTIRQ)来执行实际的、耗时较长的网络数据处理工作(如协议栈处理、将数据包传递给应用程序的 socket 缓冲区)。**软中断的执行最终是由特定的 CPU 核心来完成的。**
4. **绑核(CPU Affinity)**:“绑核”指的是将一个特定的任务(在这里,是指定网卡队列的软中断处理任务)**固定分配**给一个或一组特定的 CPU 核心去执行。
### 绑核策略
**NUMA优化**: 在 NUMA 架构的服务器上,将网卡队列绑定到与其物理位置相近(在同一 NUMA 节点内)的 CPU 核心,可以避免跨 NUMA 节点访问内存的巨大延迟开销。通常将网卡队列绑定到与网卡所在 PCIe 插槽相同 NUMA 节点的核心上,并确保处理该队列流量的应用程序线程也运行在同一个 NUMA 节点上。
**自动绑定:中断绑定随机,出现跨NUMA访问内存**

**NUMA绑定:中断绑定到指定核,避免跨NUMA访问内存**

### 网卡队列绑核记录
```bash
# 关闭irqbalance服务
systemctl stop irqbalance.service
systemctl disable irqbalance.service
systemctl status irqbalance.service
# 查看网卡队列数量
# 看 Combined 这一项的最大值 (max) 和当前设置值 (current)。
root@zzzz:~# ethtool -l eth0
Channel parameters for eth0:
Pre-set maximums:
RX: n/a
TX: n/a
Other: n/a
Combined: 31
Current hardware settings:
RX: n/a
TX: n/a
Other: n/a
Combined: 31
# 查看网卡eth0 pci 设备号 bus-info
root@zzzz:~# ethtool -i eth0
driver: mlx5_core
version: 23.10-1.1.9
firmware-version: 28.39.3674 (MT_0000000833)
expansion-rom-version:
bus-info: 0000:00:02.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: yes
# 查看网卡eth0 中断信号
# 本例中eth0的中断号为657~688
root@zzzz:~# cat /proc/interrupts |grep "0000:00:02.0"|awk '{print $1 $(NF)}'
657:mlx5_comp0@pci:0000:00:02.0
658:mlx5_comp1@pci:0000:00:02.0
659:mlx5_comp2@pci:0000:00:02.0
660:mlx5_comp3@pci:0000:00:02.0
661:mlx5_comp4@pci:0000:00:02.0
662:mlx5_comp5@pci:0000:00:02.0
663:mlx5_comp6@pci:0000:00:02.0
664:mlx5_comp7@pci:0000:00:02.0
665:mlx5_comp8@pci:0000:00:02.0
666:mlx5_comp9@pci:0000:00:02.0
667:mlx5_comp10@pci:0000:00:02.0
668:mlx5_comp11@pci:0000:00:02.0
669:mlx5_comp12@pci:0000:00:02.0
670:mlx5_comp13@pci:0000:00:02.0
671:mlx5_comp14@pci:0000:00:02.0
672:mlx5_comp15@pci:0000:00:02.0
673:mlx5_comp16@pci:0000:00:02.0
674:mlx5_comp17@pci:0000:00:02.0
675:mlx5_comp18@pci:0000:00:02.0
676:mlx5_comp19@pci:0000:00:02.0
677:mlx5_comp20@pci:0000:00:02.0
678:mlx5_comp21@pci:0000:00:02.0
679:mlx5_comp22@pci:0000:00:02.0
680:mlx5_comp23@pci:0000:00:02.0
681:mlx5_comp24@pci:0000:00:02.0
682:mlx5_comp25@pci:0000:00:02.0
683:mlx5_comp26@pci:0000:00:02.0
684:mlx5_comp27@pci:0000:00:02.0
685:mlx5_comp28@pci:0000:00:02.0
686:mlx5_comp29@pci:0000:00:02.0
687:mlx5_comp30@pci:0000:00:02.0
688:mlx5_async31@pci:0000:00:02.0
# 查看当前网卡中断绑定情况
# 本例中 657~687 中断号分别绑定在 CPU0~CPU30 上:
root@zzzz:~# for i in {657..688};do cat /proc/irq/$i/smp_affinity_list;done
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
0-179
# 如果是虚拟设备, virtio网卡
# driver: virtio_net
root@zzzz:~# ethtool -i eth0
driver: virtio_net
version: 1.0.0
firmware-version:
expansion-rom-version:
bus-info: 0000:24:00.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no
# 需要先找到对应的virtio name, 根据virtio name查看中断信号
# 本例中virtio name: virtio1
root@zzzz:~# readlink `ls -l /sys/class/net/eth0/device | awk '{print $9}'`
../../../virtio1
# 查看网卡virtio1 中断信号
# 本例中eth0的中断号为757~819
root@zzzz:~# cat /proc/interrupts | grep "virtio1-input"|awk '{print $1 $(NF)}'
757:virtio1-input.0
759:virtio1-input.1
761:virtio1-input.2
763:virtio1-input.3
765:virtio1-input.4
767:virtio1-input.5
769:virtio1-input.6
771:virtio1-input.7
773:virtio1-input.8
775:virtio1-input.9
777:virtio1-input.10
779:virtio1-input.11
781:virtio1-input.12
783:virtio1-input.13
785:virtio1-input.14
787:virtio1-input.15
789:virtio1-input.16
791:virtio1-input.17
793:virtio1-input.18
795:virtio1-input.19
797:virtio1-input.20
799:virtio1-input.21
801:virtio1-input.22
803:virtio1-input.23
805:virtio1-input.24
807:virtio1-input.25
809:virtio1-input.26
811:virtio1-input.27
813:virtio1-input.28
815:virtio1-input.29
817:virtio1-input.30
819:virtio1-input.31
# 查看当前网卡中断绑定情况
# 本例中 657~687 中断号分别绑定在 CPU0~CPU31 上:
root@zzzz:~# for i in $(seq 757 2 819);do cat /proc/irq/$i/smp_affinity_list;done
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
# 查看网卡所属 NUMA node
root@zzzz:~# ifconfig|grep UP
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 4200
eth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 4200
eth3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 4200
eth4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 4200
root@zzzz:~# for i in {0..4};do echo "eth$i: $(ethtool -i "eth$i"|grep bus-info)";done
eth0: bus-info: 0000:00:02.0
eth1: bus-info: 0000:65:01.0
eth2: bus-info: 0000:67:01.0
eth3: bus-info: 0000:69:01.0
eth4: bus-info: 0000:6b:01.0
root@zzzz:~# for i in "0000:00:02.0" "0000:65:01.0" "0000:67:01.0" "0000:69:01.0" "0000:6b:01.0"; do echo "$i: $(lspci -vvv -s $i|grep NUMA)"; done
0000:00:02.0:
0000:65:01.0: NUMA node: 0
0000:67:01.0: NUMA node: 0
0000:69:01.0: NUMA node: 1
0000:6b:01.0: NUMA node: 1
# 查看 NUMA 节点分布
root@zzzz:~# numactl -H
available: 2 nodes (0-1)
node 0 cpus: 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 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 89
node 0 size: 1002742 MB
node 0 free: 825153 MB
node 1 cpus: 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
node 1 size: 1002237 MB
node 1 free: 834099 MB
node distances:
node 0 1
0: 10 20
1: 20 10
# 修改CPU Affinity
root@zzzz:~# cat /proc/irq/657/smp_affinity_list
0
root@zzzz:~# echo 31 > /proc/irq/657/smp_affinity_list
root@zzzz:~# cat /proc/irq/657/smp_affinity_list
31
# 观察每个核心的详细使用率(特别是软中断占比)是重要的辅助手段
# 每1秒报告一次所有核心的详细使用率
# 诊断信号:某个核心的 %soft 远高于其他核心(如 CPU0=80%,其他<5%)
# %soft 列:软中断占用率
# %irq 列:硬中断占用率
mpstat -P ALL 1
# 输出示例
Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
Average: all 22.47 0.00 25.12 0.02 0.00 14.49 0.00 0.00 0.00 37.90
Average: 0 2.04 0.03 3.61 0.00 0.00 25.89 0.00 0.00 0.00 68.42
Average: 1 24.63 0.00 13.82 0.00 0.00 27.48 0.00 0.00 0.00 34.07
Average: 2 26.01 0.00 12.67 0.00 0.00 27.17 0.00 0.00 0.00 34.15
Average: 3 20.42 0.00 7.93 0.00 0.00 31.63 0.00 0.00 0.00 40.02
......
Average: 178 25.18 0.00 23.96 0.36 0.00 8.76 0.00 0.00 0.00 41.74
Average: 179 29.36 0.00 19.62 0.30 0.00 9.28 0.00 0.00 0.00 41.45
```

操作系统基础知识