☰
page_alloc zone_batchsize
2026/10/17 2:44:14 网站建设 项目流程

zone_batchsize()是 PCP(Per-CPU Pages)机制中的一个关键计算函数,用于根据 zone 的大小动态确定该 zone 的 PCP 批量大小(pcp->batch)。批量大小决定了每次从伙伴系统补充或归还 PCP 缓存时,一次操作多少页。

核心作用与设计动机

PCP 的batch值需要在减少锁竞争和控制内存滞留之间取得平衡:

  • batch 太小:频繁从伙伴系统补充/归还,锁竞争激烈,性能差;

  • batch 太大:单个 CPU 可能囤积过多页,导致其他 CPU 或内存回收无法使用这些页,内存利用率下降。

zone_batchsize()根据 zone 的管理页数(managed_pages)按比例计算一个合理的批量。

典型实现

static int zone_batchsize(struct zone *zone) { int batch; /* * 当 batch 为 1 时,PCP 缓存几乎无意义(每次只补一页), * 这里给出一个合理的下限。 * * 每个 CPU 大致可以接受最多 1/4 MB 的内存被“困”在 PCP 中。 * 假设有 NR_CPUS 个 CPU,zone 大小 / NR_CPUS / 4 就是每个 * CPU 能分到的份额。 * * 实际上不能这么做,因为 NR_CPUS 可能很大但实际 CPU 很少。 * 这里用 zone 大小的比例来计算。 */ batch = zone->managed_pages / 1024; if (batch < 1) batch = 1; /* * 将 batch 向上取整到 2 的幂,并限制在 [1, 512] 之间。 * 512 页(2MB)是经验上的合理上限。 */ batch = roundup_pow_of_two(batch + batch / 2); if (batch > 512) batch = 512; return batch; }

(实际实现随内核版本有差异,以下是核心逻辑的梳理。)

逐段解析

1. 按 zone 大小计算初始 batch

batch = zone->managed_pages / 1024; if (batch < 1) batch = 1;
  • managed_pages是 zone 被伙伴系统管理的页数(排除 reserved 等)。

  • 除以 1024 意味着:zone 越大,batch 越大,但增长是线性的。

  • 下限为 1,保证小 zone 也能正常工作。

2. 向上取整到 2 的幂,并放大 1.5 倍

batch = roundup_pow_of_two(batch + batch / 2);
  • 先放大 1.5 倍(batch + batch/2),再向上取整到 2 的幂。

  • 取 2 的幂是为了对齐方便(伙伴系统、PCP 链表操作都偏好 2 的幂)。

  • 放大 1.5 倍是为了给 batch 留些余量,减少补充频率。

3. 上限 512 页

if (batch > 512) batch = 512;
  • 512 页 = 2MB,是经验上的合理上限。

  • 防止大内存机器上单个 CPU 囤积过多页,影响内存利用率和回收效率。

历史演进:从batch到high_min/high_max

2023 年前后,PCP 的调节机制经历了重要重构:

旧机制:zone_batchsize()计算batch,然后zone_pcp_init()用batch推导high(高水位),关系大致是high = batch * 6。batch和high都是静态的,启动后不再变化。

新机制:引入high_min/high_max,pcp->high可以在运行时动态增长和衰减:

  • nr_pcp_alloc()在分配压力大时抬高high;

  • decay_pcp_high()在压力小时降低high;

  • batch本身仍由zone_batchsize()计算,但high的调节更灵活。

这个重构让 PCP 能自适应工作负载,在大内存机器上更高效,在内存紧张时更快回流。

调用位置

zone_batchsize()被zone_pcp_init()调用:

static void __meminit zone_pcp_init(struct zone *zone) { zone->per_cpu_pageset = &boot_pageset; if (populated_zone(zone)) zone->pageset = &boot_pageset; if (zone->present_pages) pr_debug(" %s zone: %lu pages, LIFO batch:%u\n", zone->name, zone->present_pages, zone_batchsize(zone)); }

zone_batchsize()的计算结果会影响后续per_cpu_pages_init()中pcp->batch的初始化。

总结

zone_batchsize()是PCP 批量大小的计算器:它根据 zone 的managed_pages按比例(1/1024)计算初始 batch,放大 1.5 倍并向上取整到 2 的幂,最后限制在 [1, 512] 页之间。它平衡了锁竞争(batch 大)和内存滞留(batch 小)的矛盾,是 PCP 机制自适应不同 zone 大小的关键。2023 年后的重构让high水位能动态调节,而batch仍是这个函数计算的基础值。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询