
nr_pcp_free()是 PCPPer-CPU Pages缓存批量释放策略的核心计算函数它决定了当pcp-count超过高水位时一次性应该释放多少页归还给伙伴系统。这个返回值直接影响free_pcppages_bulk()的行为是平衡“锁竞争”与“延迟”的关键。核心作用计算单次批量释放的页数当 PCP 缓存积累的页数超过高水位pcp-count high时内核需要触发批量释放。nr_pcp_free()负责根据当前缓存状态计算出一个最优的释放批量而非简单地释放固定数量。核心逻辑与演进该函数的实现经历过多次调整核心逻辑围绕缩放批量展开以平衡两个矛盾的目标减少zone-lock竞争一次性释放更多页减少获取全局锁的次数。控制延迟与内存压力避免单次释放过多页导致其他线程饥饿或内存回收滞后。经典实现使用free_factor缩放在早期设计中它通过free_factor来指数级放大批量释放的规模static int nr_pcp_free(struct per_cpu_pages *pcp, int high, int batch) { int min_nr_free, max_nr_free; /* PCP 禁用或启动阶段只释放 1 页 */ if (unlikely(high batch)) return 1; min_nr_free batch; // 至少释放一个 batch保证下次分配还有页可用 max_nr_free high - batch; // 最多释放到只剩一个 batch batch pcp-free_factor; // 指数放大 if (batch max_nr_free) pcp-free_factor; // 连续释放时进一步放大 batch clamp(batch, min_nr_free, max_nr_free); return batch; }核心思想是连续释放时逐步增大释放批量翻倍直到达到上限而一旦发生分配free_factor会减半pcp-free_factor 1让批量回缩。2023 年的重构使用free_count后续补丁将free_factor改为free_count用于追踪连续释放的页数批量计算方式也改为基于free_count进行钳制static int nr_pcp_free(struct per_cpu_pages *pcp, int batch, int high, bool free_high) { int min_nr_free, max_nr_free; /* 批量释放高阶页时尽可能多释放 */ if (unlikely(free_high)) return min(pcp-count, batch CONFIG_PCP_BATCH_SCALE_MAX); if (unlikely(high batch)) return 1; min_nr_free batch; max_nr_free high - batch; /* 根据连续释放的页数来钳制批量 */ batch clamp_t(int, pcp-free_count, min_nr_free, max_nr_free); return batch; }关键设计点1. 保留下限min_nr_free batch无论何时释放后 PCP 中至少保留一个batch的页确保下一次分配可以立即从 PCP 满足而不必去竞争zone-lock。2. 上限保护max_nr_free high - batch单次释放不能过多避免把 PCP 一次性清空导致后续分配频繁访问伙伴系统。3.free_high的特殊处理当触发free_high启发式检测到连续释放高阶页可能造成碎片时函数会尽可能多地释放甚至一次性排空return pcp-count以迅速缓解碎片压力。总结nr_pcp_free()是 PCP 缓存释放策略的“节流阀”它根据连续释放的规模free_factor或free_count动态计算单次批量释放的页数——连续释放时逐步放大批量以减少锁竞争同时始终保留至少一个batch以维持分配性能。触发free_high时则激进释放以对抗碎片。