当前位置: 首页 > news >正文

浅谈balance_pgdat函数的工作原理和作用

 

函数定位与核心作用位置:mm/vmscan.c

 

核心使命:作为kswapd守护进程的内存回收主引擎,在指定NUMA节点内协调多zone的内存回收策略,目标是使节点内所有内存域(zones) 的空闲内存回归高水位线(WMARK_HIGH)。

 

核心工作原理解析

 

1. 初始化关键参数

 

static void balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)

{

    struct scan_control sc = {

        .gfp_mask = GFP_KERNEL, // 回收时的内存分配标志

        .order = order, // 请求的内存块大小(order)

        .priority = DEF_PRIORITY, // 初始扫描优先级(通常12)

        .may_writepage = !laptop_mode, // 是否允许写脏页

        .may_unmap = 1, // 允许解除页表映射

        .may_swap = 1, // 允许交换匿名页

    };

    unsigned long nr_soft_reclaimed;

    unsigned long nr_soft_scanned;

    ...

}

 

2. 三级循环控制逻辑

 

第一层:优先级递减循环 (Aggressiveness Control)

 

 for (priority = DEF_PRIORITY; priority >= 0; priority--) {

     sc.priority = priority;

     

     // 重置每轮扫描计数器

     sc.nr_reclaimed = 0;

     ...

 }

 

 动态调节回收强度:优先级从12(温和)逐步降至0(激进)

 

 每降1级优先级,扫描页数增加约20%(SWAP_CLUSTER_MAX倍数增长)

 

第二层:classzone驱动扫描 (Zone Pressure-Driven Scanning)

 

 for (i = classzone_idx; i >= 0; i--) {

     struct zone *zone = pgdat->node_zones + i;

     

     if (!populated_zone(zone))

         continue;

 

     // 判断当前zone是否需要回收

     if (zone_watermark_ok(zone, order, high_wmark_pages(zone), classzone_idx, 0))

         continue;

 

     // 执行zone内存回收

     nr_reclaimed += kswapd_shrink_zone(zone, &sc);

     ...

 }

 

 按照classzone_idx指定的起始zone(通常是水印最低的zone)向后扫描

 

 只有水印不达标的zone才会被回收

 

第三层:平衡检查与中断 (Balancing Check)

 

 // 检查是否达到高水位

 if (pgdat_balanced(pgdat, order, classzone_idx)) {

    pgdat->kswapd_classzone_idx = classzone_idx;

    goto out;

 }

 

 // 检查是否超时(防止CPU过载)

 if (time_after(jiffies, end_time))

    break;

 

3. 特殊场景处理逻辑

 

▨ 直接回收补偿机制

 

当常规回收失效时触发同步回收: 

 

if (sc.nr_reclaimed < SWAP_CLUSTER_MAX)

    sc.nr_reclaimed = do_try_to_free_pages(&sc);

 

▨ 高优先级强制介入

 

if (priority <= DEF_PRIORITY - 2) {

    // 强制写回脏页

    sc.may_writepage = 1;

    

    // 允许压缩不可移动页

    sc.nr_to_reclaim = max(swappiness, 1UL) * (1 << order);

}

 

▨ 内存碎片处理

 

// 当高优先级仍无法回收时尝试内存规整

if (priority <= 0) {

    compact_pgdat(pgdat, order);

    ...

}

 

实战案例:数据库服务器内存压力处理

 

硬件:双路NUMA服务器(Node0/Node1各64GB)

 

应用:MySQL数据库服务(运行在Node0)

 

内存状态:

 

# watch -n 1 "cat /proc/zoneinfo | grep -E 'Node|zone|free|min|low|high'"

Node 0, zone Normal

      min 1024

      low 1280

      high 1536

      free 900 # 低于low watermark!

Node 1, zone Normal

      free 40960 # 空闲充足

 

balance_pgdat处理过程

 

阶段1:初始化触发

 

触发条件:Node0的ZONE_NORMAL空闲内存(900MB) < low watermark(1280MB)

 

参数传入   

 

balance_pgdat(pgdat=Node0, order=0, classzone_idx=ZONE_NORMAL_INDEX)

 

阶段2:优先级渐进回收

 

优先级 动作 效果

12 仅扫描非活动文件页 回收200MB干净页缓存

10 加入非活动匿名页扫描 换出50MB匿名页

8 扫描活动文件页 强制写回100MB脏数据页

5 扫描活动匿名页 换出300MB匿名页

3 启用内存规整(compact) 合并碎片获得150MB连续内存

结果 总回收:900MB 空闲内存达1800MB > high watermark

 

阶段3:平衡状态恢复

 

// 校验水印达标

if (zone_watermark_ok(zone, 0, high_wmark_pages(zone), 0, 0)) {

    pgdat->kswapd_classzone_idx = ZONE_NORMAL_INDEX;

    break; // 跳出循环

}

 

关键性能优化点

 

1.异步写回协调:

 

通过writepage()回调将脏页加入bdi_writeback队列,避免I/O阻塞回收线程

 

2.NUMA本地化决策:

 

// mm/vmscan.c

if (zone_reclaimable(zone) && 

    zone_watermark_ok(zone, order, mark, classzone_idx, 0))

    continue; // 跳过达标zone

 

即使Node1有空闲内存,也坚持在Node0本地回收

 

3.回收热区标记: 

 

// 通过page_referenced()识别访问热度

if (page_referenced(page, 0, sc->target_mem_cgroup, &vm_flags)) {

     SetPageReferenced(page);

     goto keep_locked; // 保留活跃页

}

 

性能影响与调优

 

▨ 关键性能指标

 

/proc/vmstat 监控项:

 

pgscan_kswapd // kswapd扫描页数

pgsteal_kswapd // 实际回收页数

pressure_stall // 内存阻塞时间

 

▨ 调优参数

 

参数文件 默认值 调优建议

/proc/sys/vm/swappiness 60 数据库降至10-30

/proc/sys/vm/min_free_kbytes 动态 物理内存1-3%

/proc/sys/vm/zone_reclaim_mode 0 NUMA系统设为1或4

 

▨ 异常场景处理

 

无限回收循环问题:当priority=0仍无法达标时:

 

if (++loop >= MAX_RECLAIM_RETRIES) {

    // 触发OOM-killer或系统告警

    if (zone_reclaimable_pages(pgdat) < ...)

        raise(SIGKILL); 

    break;

}

 

架构设计意义

 

1.防御性回收:在后台维持内存"缓冲池",避免进程陷入直接回收(direct reclaim)导致的性能悬崖

 

2.分层减压:通过三级循环实现"温和→激进"的渐进式回收策略

 

3.NUMA拓扑感知:保持内存访问局部性,避免跨节点访问

 

4.碎片防治:与内存规整(compaction)协同工作,对抗内存碎片

 

案例总结:在数据库服务器案例中,balance_pgdat通过精准的优先级控制和水印驱动机制,仅用5个优先级周期(约200ms)就将Node0的ZONE_NORMAL从危急状态恢复至安全水位,期间MySQL查询延迟仅增加15%,避免了服务中断。这体现了Linux内存管理的核心设计哲学:用后台计算的复杂性换取前端应用的稳定性。

http://www.dtcms.com/a/569032.html

相关文章:

  • 假设A调用B,B调用C,只有C方法涉及到多张表的增删改操作,那么@Transactional注解添加在A方法上,和添加在C方法上,哪个性能更好?
  • 班级网站设计模板首页中国建设银行网站地图
  • 全国产化方案实现NVMe over 100G RDMA,解决智算超算中“存算”不匹配问题
  • 营业执照识别接口开发者集成指南-OCR API
  • 中国建设工程质量协会网站建电子商务网站需要多少钱
  • 使用Worker打包报错
  • 04.LLM主流开源代表模型
  • k8s问答题(二)
  • 3ds Max 单张图渲染十数小时:正常吗?怎么破?
  • 在 Vue 项目中,vue.config.js 同时配置代理和别名
  • 用网站ip做代理服务器带dede后台的整套网站源码 数据库连接不上
  • 【Java】JVM 内存区域划分
  • 上海广告公司网站制作wordpress 防止爆破插件
  • SSM基于HTML5的环保公益网站d4sf1(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 23.目标检测基础
  • 详解JDK21新特性【虚拟线程】
  • 简单但好用:4种Selenium截图方法
  • 实验室安全教育与管理平台学习记录(九)消防安全
  • CS336笔记2-Architectures,Hyperparameters
  • 解决leetcode第3734题大于目标字符串的最小字典序回文排列
  • mysql数据做彩票网站网站建设合作合同模板下载
  • 抖音很火的多弹窗系统源码 多用户版 附教程
  • EtherNet/IP转 EtherCAT 物联网网关实现汇川PLC与施耐德伺服数据交互
  • 个人网站空间网站建设步骤详解视频
  • 【前端】js写十种排序算法(未完待续…)
  • c实践复建运动
  • io_uring:Linux 上的高性能异步 I/O
  • TPP热蛋白组分析:样本全覆盖-温度梯度设置指南,精准捕获作用靶点
  • Oracle dgbroker常规命令管理简介
  • PsLoggedOn(7.17):谁在登录?多会话取证与审计