zone_highsize()是 PCPPer-CPU Pages缓存机制中用于计算pcp-high高水位值的核心函数。它决定了每个 CPU 的 PCP 缓存最多可以“囤积”多少空闲页超过这个数量就会触发批量归还给伙伴系统。核心作用动态计算高水位pcp-high的设定需要在减少锁竞争和控制内存滞留之间取得平衡high 太小PCP 缓存很快填满频繁批量归还zone-lock竞争加剧high 太大单个 CPU 囤积过多页导致其他 CPU 或内存回收无法使用这些页。zone_highsize()根据 zone 大小、在线 CPU 数量以及用户配置动态计算出一个合理的high值。函数签名与参数static int zone_highsize(struct zone *zone, int batch, int cpu_online, int high_fraction)参数含义zone目标 zonebatch该 zone 的 PCP 批量大小由zone_batchsize()计算cpu_online额外计入的在线 CPU 数量用于处理 CPU 热插拔的竞态high_fraction用户配置的比例值0 表示使用默认策略两种计算策略函数的核心逻辑根据high_fraction分两条路径策略一默认策略high_fraction 0total_pages low_wmark_pages(zone);pcp-high基于 zone 的低水位线WMARK_LOW计算。这样设计的原因是如果 PCP 缓存填满达到 high后续的分配不会过早触发后台回收kswapd。因为 PCP 中缓存的页在释放时会归还伙伴系统如果 high 设置得比低水位线还高回收逻辑会认为“内存充足”但实际上这些页被“困”在 PCP 里导致真正的可用内存被高估。策略二用户配置策略high_fraction 0total_pages zone_managed_pages(zone) / high_fraction;用户通过vm.percpu_pagelist_high_fractionsysctl 指定一个比例。high_fraction 8意味着“每个 CPU 的 PCP 最多可以缓存 zone 管理页数的 1/8”。这个值有一个下限MIN_PERCPU_PAGELIST_HIGH_FRACTION 8防止配置过小导致 PCP 失效。按 CPU 数量分配计算出total_pages后函数会将其按 CPU 数量均分nr_split_cpus cpumask_weight(cpumask_of_node(zone_to_nid(zone))) cpu_online; high total_pages / nr_split_cpus;cpumask_weight(cpumask_of_node(...))该 zone 所属 NUMA 节点上的 CPU 数量cpu_online处理 CPU 热插拔时的竞态上线过程中cpumask可能尚未更新对于没有 CPU 的 memory node会按所有在线 CPU 均分避免因 PCP 缓存页过多而过早触发回收。保证 high 不低于 batch 的 4 倍high max(high, batch 2);这是一个历史遗留的约束high至少是batch的 4 倍。如果high太小PCP 缓存刚补充一批页就立刻触发归还批量补充的收益就没了。在 PCP 调节机制中的位置zone_highsize()被zone_set_pageset_high_and_batch()调用后者在 zone 初始化、CPU 热插拔、内存热插拔时更新所有 CPU 的 PCP 配置static void zone_set_pageset_high_and_batch(struct zone *zone, int cpu_online) { int new_high, new_batch; new_batch max(1, zone_batchsize(zone)); new_high zone_highsize(zone, new_batch, cpu_online); if (zone-pageset_high new_high zone-pageset_batch new_batch) return; zone-pageset_high new_high; zone-pageset_batch new_batch; __zone_set_pageset_high_and_batch(zone, new_high, new_batch); }历史演进从手动调节到自动调节zone_highsize()的high_fraction参数是 2023 年 PCP 高水位自动调节机制引入后的产物。在此之前pcp-high是静态的只在 zone 初始化或 sysctl 修改时计算一次。用户通过vm.percpu_pagelist_high_fraction手动调节但这个值难以找到最优解且全局配置无法适应不同工作负载。引入自动调节后pcp-high可以在high_min和high_max之间动态变化high_min是zone_highsize(zone, batch, cpu_online, 0)计算出的默认值基于低水位线high_max是zone_highsize(zone, batch, cpu_online, MIN_PERCPU_PAGELIST_HIGH_FRACTION)计算出的上限用户配置的最大值如果用户手动设置了percpu_pagelist_high_fraction则high_min和high_max都设为该手动值禁用自动调节。这个设计让 PCP 能够自适应工作负载分配压力大时自动抬高high减少锁竞争压力小时自动降低high加快内存回流。总结zone_highsize()是PCP 高水位的计算器它根据high_fraction决定是采用默认策略基于 zone 低水位线还是用户配置策略基于 zone 管理页数的比例然后按 NUMA 节点上的 CPU 数量均分最后保证high不低于batch的 4 倍。它的high_fraction参数是 PCP 自动调节机制的关键——0表示使用默认最小值MIN_PERCPU_PAGELIST_HIGH_FRACTION表示用户允许的最大值两者之间的区间就是pcp-high可以自动调节的范围。
阅读完成 · 觉得有帮助?