4.7.6 内存优化实践:大页、缓存回收与参数调优

内存优化实践:大页、缓存回收与参数调优#

内存优化需围绕“减少TLB miss、稳定页缓存回写、避免过量分配与高阶页分配失败”展开。以下内容包含原理草图、可执行命令、参数配置、排错与练习,便于直接落地。

flowchart TD
  A[应用内存访问] --> B[页表与TLB]
  B --> C[物理页: 4K]
  B --> D[大页: 2M/1G]
  C --> E[页缓存(Page Cache)]
  E --> F[脏页回写]
  F --> G[磁盘IO]
  C --> H[swap]

1. 大页(HugePages/THP)优化#

适用场景:内存密集型数据库、JVM、缓存类服务。
原则:显式大页可控但占用固定内存;THP易用但可能引起抖动。

查看与判断

# 查看显式大页信息
grep -E "HugePages|Hugepagesize" /proc/meminfo

# 查看THP状态
cat /sys/kernel/mm/transparent_hugepage/enabled

配置显式大页(建议在业务低峰)

# 计算需要的页数(示例:2M页,预留2GB)
# 2GB / 2MB = 1024
echo 1024 > /proc/sys/vm/nr_hugepages

# 确认已分配
grep -E "HugePages_Total|HugePages_Free" /proc/meminfo

关闭THP(常见数据库推荐)

# 临时关闭
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 永久关闭(示例:systemd)
cat >/etc/systemd/system/disable-thp.service <<'EOF'
[Unit]
Description=Disable Transparent Huge Pages
After=sysinit.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c "echo never > /sys/kernel/mm/transparent_hugepage/enabled; echo never > /sys/kernel/mm/transparent_hugepage/defrag"

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now disable-thp.service

效果验证

# 观察内存命中与抖动
vmstat 1 5

# 若业务允许,配合压力测试对比p99延迟

排错
- 大页分配失败:内存碎片严重,重启或在低峰预留;适当调高 vm.min_free_kbytes
- 关闭THP后性能下降:尝试显式大页或仅关闭defrag。


2. 缓存回收与页缓存控制#

关键指标与命令

# 可用内存与缓存占用
free -m

# 回收压力与swap
vmstat 1 5

# 观察脏页、回写
grep -E "Dirty|Writeback|Cached" /proc/meminfo

应急清理页缓存(仅排障,不建议长期频繁)

# 同步脏页后释放缓存
sync
echo 3 > /proc/sys/vm/drop_caches

# 预期:Cached下降,业务IO可能短时波动

脏页回写参数调优(示例:降低回写抖动)

# 临时调整
sysctl -w vm.dirty_background_ratio=5
sysctl -w vm.dirty_ratio=15
sysctl -w vm.dirty_writeback_centisecs=500
sysctl -w vm.dirty_expire_centisecs=3000

# 持久化
cat >>/etc/sysctl.conf <<'EOF'
vm.dirty_background_ratio = 5
vm.dirty_ratio = 15
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000
EOF

sysctl -p

效果验证

# 观察回写峰值是否平滑
vmstat 1 10 | awk '{print $1,$2,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15}'

排错
- IO突刺:降低 dirty_ratiodirty_background_ratio
- 延迟尖刺:缩短 dirty_writeback_centisecs,避免积累过多脏页。


3. 关键内核参数调优#

Swappiness

# 低延迟服务推荐 1~10
sysctl -w vm.swappiness=10

# 持久化
echo "vm.swappiness = 10" >> /etc/sysctl.conf
sysctl -p

VFS缓存压力

# 文件访问频繁场景:降低回收力度
sysctl -w vm.vfs_cache_pressure=50

内存过量分配

# 数据库建议:严格模式
sysctl -w vm.overcommit_memory=2
sysctl -w vm.overcommit_ratio=90

最小保留内存

# 大内存机器适度提高,避免高阶页分配失败
sysctl -w vm.min_free_kbytes=262144

排错
- 内存充足仍触发OOM:检查 overcommit 与 cgroup 限制。
- 高阶页分配失败:提高 min_free_kbytes,或关闭THP。


4. 实践流程(含完整示例)#

目标:在生产前验证参数对延迟与抖动的影响。

# 1) 采集基线
free -m
vmstat 1 5
sar -r 1 5

# 2) 单项调参(示例:降低回写抖动)
sysctl -w vm.dirty_background_ratio=5
sysctl -w vm.dirty_ratio=15

# 3) 压测(示例:fio顺序写)
fio --name=write_test --filename=/data/testfile \
--size=2G --bs=1M --rw=write --direct=0 --iodepth=8 --numjobs=1

# 4) 观察效果
vmstat 1 5

预期效果
- 回写峰值降低,vmstatbo 波动减小;
- 应用 p99 延迟更稳定。


5. 常见问题与处理#

  • 内存明明充足仍被OOM Kill
    检查 vm.overcommit_memoryovercommit_ratio、cgroup限制与大页占用。
  • 频繁swap
    降低 swappiness,排查进程泄漏,必要时扩容。
  • IO抖动严重
    调低 dirty_ratiodirty_background_ratio,检查存储性能。
  • 大页分配失败
    低峰预留,增加 min_free_kbytes,或重启整理碎片。

6. 练习#

  1. 大页验证:预留1024个大页,观察 HugePages_Free 变化,并写出回滚步骤。
  2. 脏页回写实验:对比 dirty_ratio=40dirty_ratio=15fio 写入抖动。
  3. OOM复现:在测试机中设置 overcommit_memory=2,启动超大内存进程,观察失败日志并分析原因。