精读笔记(RHCA 英文教材)· RH442 Chapter 8 Tuning Memory Utilization
精读笔记(RHCA 英文教材)· RH442 Chapter 8 Tuning Memory Utilization
教材原文:RHCA 官方英文教材(PDF 第 296~345 页)(OCR 整书版已从本站移除,本页为章节精读) 关联中文笔记:
02-09-性能调优RH442(RHCA).md(内存 free/vmstat、页缓存、swap 策略 vm.swappiness);本章=内存调优四大块:架构/页表/TLB/大页 → 分页回收/脏页 → NUMA → overcommit/OOM。 结构:4 个 Section(8.1 内存架构+GE memtuning-arch;8.2 分页与回收+GE memtuning-paging;8.3 NUMA+GE memtuning-numa;8.4 内存 Overcommit+GE memtuning-overcommit)+ Lab(lab: memtuning-review)。
Chapter Goal / Objectives(原文+译)
- GOAL: Manage settings for efficient use of system memory.(管理内存高效使用的设置。)
- OBJECTIVES: ① 描述内存架构(虚拟内存/缓存/大页/进程空间);② 描述并配置系统分页行为;③ 描述并配置 NUMA;④ 管理内存 overcommit 策略。
8.1 Configuring Memory Architecture
- 页与虚拟内存:物理内存按**页(page,默认 4KiB)**分页框;进程不直接寻址物理内存,各有虚拟地址空间(x86-64 理论 2⁶⁴;新 CPU 留高 7 位只用 57 位→可寻 128 PiB;旧 CPU 留 16 位用 48 位→256 TiB)。
/proc/cpuinfo的address sizes: … physical, … virtual可查。 - 页表与 TLB:每进程一张页表(分层页目录结构,用多少建多少,避免几百 GiB 大表)。CPU 用 TLB(Translation Lookaside Buffer) 缓存近期地址映射,顺序访问同一页很快;TLB miss→查页表→真缺页才进内存。
perf stat -e dTLB-load-misses firefox可查数据 TLB miss(⚠️ VM 里不可用)。上下文切换常要冲刷 TLB。 - 限制进程内存:systemd drop-in
[Service] MemoryLimit=1G(K/M/G/T 后缀);也可systemctl set-property sshd.service MemoryLimit=1G(自动生成 /etc/systemd/system.control 下 drop-in)。 - 缺页监控:
perf stat -e minor-faults:u,major-faults:u firefox等。 - Huge Pages(大页):
- 页太大导致 TLB 条目少、数据库类进程 TLB miss 多→用大页(RHEL 默认 2 MiB,
hugepagesz=引导参数可改,/proc/meminfo 的 Hugepagesize 可查)。TLB 一条映射 2 MiB,命中率大增。 - 分配:
sysctl -w vm.nr_hugepages=20(要连续空闲内存;不够只给部分)。NUMA 上默认均分到各节点;要集中某节点写/sys/devices/system/node/nodeN/hugepages/hugepages-2048kB/nr_hugepages(numastat -cm可查分布)。 - ⚠️ 只有大页感知应用能用(mmap() 或 shmat()/shmget() 申请);mmap 方式需挂
hugetlbfs(RHEL8 systemd 开机自动挂)。普通进程用不了预留大页=浪费。 - THP(透明大页):内核自动分配/管理(可换出,异于标准大页)。开关
/sys/kernel/mm/transparent_hugepage/enabled:always(开)/never(关)/madvise(只给主动 madvise 的进程)。khugepaged 守护在 always/madvise 时自动扫描合并页。查用量grep AnonHugePages /proc/meminfo。tuned 档里[vm] transparent_hugepages=never;也可内核引导参数transparent_hugepage=。数据库等应用常关 THP(缺页/合并开销、不可预测性)。
- 页太大导致 TLB 条目少、数据库类进程 TLB miss 多→用大页(RHEL 默认 2 MiB,
8.1 GE(lab: memtuning-arch)
servera:用 bigmem 观察内存分配;perf stat 看 minor/major faults;配 vm.nr_hugepages/按节点 nr_hugepages、看 /proc/meminfo HugePages_*;比较 THP always/never(AnonHugePages)。
8.2 Configuring Memory Paging and Reclamation
- 内存两大用途:page cache(缓存磁盘读写数据;重复访问同文件收益大;只读一次的流媒体没价值)+ 匿名页 anon(进程工作数据,与磁盘无关)。
free/vmstat看:buff/cache 大≠内存不够(available 列=可释放缓存后的可用量);主动 drop cache 会伤 I/O 性能。 - Direct I/O:数据库自带缓存时绕开 page cache(直读块设备或文件直 I/O)。
- 回收/swap:内存压力下内核可选换出匿名页到 swap(换入时要 major fault,比 RAM 慢)或回收 page cache。working set=进程活跃页集合;压力下先换出非活跃页,保持 working set 在 RAM 则性能不受影响。
- vm.swappiness(0~100):调"回收匿名页 vs 回收页缓存"的倾向。=100:几乎总是先换出匿名页、保留 page cache(I/O 重负载/文件服务器最佳);=1:尽量少 swap(响应性好但伤文件系统性能;数据库这类不用 page cache 的应用受益);RHEL8 默认 30(2009 前 RHEL 默认 60)。⚠️ 教材说不建议用 0(现代内核 0 与其他值语义相近但风险高),用 1 表达"最小 swap"。
- 页状态:Free / Active(在用,不释放)/ Inactive clean(内容与磁盘一致,可先回收)/ Inactive dirty(改过未写回,须先回写)。看 /proc/meminfo 的 Active/Inactive(file/anon)/Dirty/Writeback;进程级看
/proc/<pid>/smaps(Shared_Clean/Dirty 等,awk 汇总)。 - 脏页回写(flush 线程):系统周期把脏页写盘防断电丢数据(每块设备一个 flush-MAJOR:MINOR 内核线程,需要才启动)。相关 sysctl:
vm.dirty_expire_centisecs:脏页多老(1/100 秒)才考虑写(默认 500=5 秒;防进程频繁改同页导致重复写)。vm.dirty_writeback_centisecs:多久唤醒 flush 线程一次(默认 100=1 秒;=0 关闭周期回写)。vm.dirty_background_ratio:脏页占内存百分比达到即后台开始写。vm.dirty_ratio:达到该百分比时进程自身写操作被阻塞强制刷盘。
- OOM 处理:真无内存+swap 时触发 OOM killer(默认选杀进程释放内存,可能损坏应用数据);可设
vm.panic_on_oom=1让内核 panic 而非杀进程(配合 watchdog 重启)。NUMA 上节点内存耗尽会触发节点级 OOM/回收(见 NUMA 节)。 - oom_score 调整:systemd drop-in
[Service] OOMScoreAdjust=-1000(-1000=免疫~1000=优先被杀),改后 daemon-reload+restart;运行时也可写 /proc/<pid>/oom_score_adj。
8.2 GE(lab: memtuning-paging)
servera:观察 free/vmstat、/proc/meminfo 页状态;调 vm.swappiness、dirty_* 参数并制造脏页/swap 压力看回写行为(第二终端 watch),验证参数对 I/O 负载的影响。
8.3 Configuring NUMA Topology
- UMA vs NUMA:老式多 CPU 共享前端总线(所有内存等速);现代每 CPU 包直连一组内存(本地快、远端走高速互联慢)→ NUMA。Linux 把系统分成 node(=物理 CPU+其本地内存);I/O 控制器也与部分 CPU 直连(跑在设备同节点更优)。
- 自动机制:RHEL7+ automatic NUMA balancing(内核自动迁移任务/内存,
kernel.numa_balancingsysctl 控制);RHEL6 时代用 numad 用户态守护(用 numad 需关自动平衡:sysctl kernel.numa_balancing=0)。对长时间跑的资源大户收益最大;几秒的轻量进程没必要。 - 查看拓扑:
numactl --hardware(每节点 cpus/size/free + node distances 距离矩阵);lstopo/numastat -cm(每节点内存与 huge page 分布);numastat(每进程在哪些节点分配)。 - 放置策略:
numactl --cpunodebind=N --membind=N <cmd>(CPU 与内存同节点);--preferred只偏好不强制;配合 taskset/cpuset 做细粒度绑定。
8.3 GE(lab: memtuning-numa)
servera:numactl --hardware/lstopo 看节点;用 bigmem 分配 600 MiB 观察默认节点分布;numactl --cpunodebind/--membind 绑节点重跑对比(numastat 看 per-node 分配变化)。
8.4 Managing Memory Overcommit
- overcommit 概念:进程 malloc 大量虚拟内存但不用时内核并不真给物理页(按需调页)。内核接受与否由策略决定。
- vm.overcommit_memory 三模式:
0(默认):启发式——明显超卖的大块申请拒绝、小块接受(内核拒绝 20 GiB 单块、接受 1 MiB 分块 20 GiB)。1:总是 overcommit——任何分配都答应(危险,但大内存应用/某些数据库工作负载用)。2:严格模式——最多承诺 "swap +vm.overcommit_ratio(默认 50)% 的物理内存"。
- 验证:
/proc/meminfo的CommitLimit(允许上限)与Committed_AS(已承诺量);watch grep Commit /proc/meminfo实时看余量。
8.4 GE(lab: memtuning-overcommit)
servera:默认启发式下 bigmem 小分块分配 20 GiB 成功、--block 单大块失败 → 设 overcommit_memory=1 后单块也成功 → 设=2+算 overcommit_ratio 使上限≈2×RAM+swap,验证刚好在上限内成功、超限 malloc 失败。
Lab 概要(lab: memtuning-review)
serverb:为 memload 服务建 systemd 单元(分配内存、huge pages 相关配置),按要求设 HugePages/内存限额/OOMScore,压测观察 CommitLimit/OOM 行为 → lab grade memtuning-review。
命令速查表
| 用途 | 命令 | | 内存概览/压力 | free -m;vmstat 1;grep -E 'Active|Dirty|Huge|Commit' /proc/meminfo | | 大页 | sysctl -w vm.nr_hugepages=20;按节点写 /sys/devices/system/node/nodeN/hugepages/hugepages-2048kB/nr_hugepages | | THP | echo never > /sys/kernel/mm/transparent_hugepage/enabled(always/never/madvise) | | 进程内存 | systemd drop-in MemoryLimit;systemctl set-property <u> MemoryLimit=1G;/proc/<pid>/smaps | | TLB/缺页 | perf stat -e dTLB-load-misses,minor-faults,major-faults <cmd>(VM 无硬件事件) | | swap/脏页 | sysctl vm.swappiness=1;vm.dirty_expire_centisecs / dirty_writeback_centisecs / dirty_background_ratio / dirty_ratio | | OOM | sysctl vm.panic_on_oom=1;drop-in OOMScoreAdjust=-1000;/proc/<pid>/oom_score_adj | | NUMA | numactl --hardware;numastat [-cm];numactl --cpunodebind=N --membind=N <cmd>;sysctl kernel.numa_balancing | | overcommit | sysctl vm.overcommit_memory=0\|1\|2;vm.overcommit_ratio=50;/proc/meminfo CommitLimit/Committed_AS | | 实验/评分 | lab start memtuning-arch\|memtuning-paging\|memtuning-numa\|memtuning-overcommit\|memtuning-review;lab grade memtuning-review |
词汇表
| 英文 | 中文 | 速记 |
|---|---|---|
| page / page frame | 页/页框 | 默认 4KiB |
| page table / TLB | 页表/旁路转换缓冲 | 地址翻译缓存;miss 进页表 |
| huge pages / THP | 大页/透明大页 | 2MiB;THP 内核自动管可换出 |
| hugetlbfs | 大页文件系统 | mmap 方式用大页需挂载 |
| working set | 工作集 | 活跃页集合,保住它性能不掉 |
| swappiness | 换出倾向 | 100 保 page cache;1 最小 swap |
| page cache / anon pages | 页缓存/匿名页 | 磁盘缓存 vs 工作数据 |
| dirty page & flush | 脏页与回写 | dirty_ratio 系列控制 |
| OOM killer / oom_score_adj | OOM 杀手/分数 | -1000 免疫~1000 先杀 |
| NUMA node | 非一致内存节点 | CPU+本地内存;本地快 |
| numactl / numastat | NUMA 工具 | bind 与查看 |
| overcommit | 超量承诺 | 0 启发/1 全答应/2 严格 |
| CommitLimit / Committed_AS | 承诺上限/已承诺量 | /proc/meminfo 验证 |
自测 10 题
- x86-64 进程虚拟地址空间多大?(理论 2⁶⁴;新 CPU 实际 57 位=128 PiB)
- TLB 是什么、miss 多怎么办?(地址翻译缓存;用大页减少条目压力)
- RHEL 默认大页多大?(2 MiB;hugepagesz= 可改)
- THP 三取值含义?(always/never/madvise;khugepaged 只在前两者启动)
- swappiness=100 与 =1 各适合什么?(I/O 重负载保缓存;DB 等保响应少 swap)
- 脏页后台/强制回写的参数?(dirty_background_ratio 后台;dirty_ratio 阻塞写)
- OOMScoreAdjust 取值范围?(-1000 免疫 ~ 1000 优先被杀)
- NUMA 自动平衡与 numad 关系?(RHEL7+ 内核自动平衡;用 numad 须关 kernel.numa_balancing)
- 查看 NUMA 节点分布用什么?(numactl --hardware、numastat -cm)
- overcommit_memory=2 允许承诺多少?(swap + overcommit_ratio%(默认50)物理内存)
