-
恢复 nokmem 下 NONSLAB shrinker 的 per-memcg 回收
让 cgroup.memory=nokmem 下 THP deferred split 与 zswap 两个 shrinker 恢复 per-memcg 回收:list_lru xarray 改用与 kmem 计费无关的 cgroup ID 索引,内部遍历直传索引不做反解,NONSLAB 支撑的 lru 在 nokmem 下保持 memcg 感知,两个 shrinker 补上 SHRINKER_NONSLAB 标志,limit 回收重新精准拆分 THP 并回写 zswap 页
-
延迟 inode 回收
回收部分 inode 要做日志等文件系统 IO,IO 里的 GFP_NOFAIL 分配在回收上下文无法保证前向进度,MM 报警甚至锁死;把难回收的 inode 打标后卸载给一组并行 worker 回收,iput() 对回收路径上最后引用的已删 inode 自动延迟,lazytime 改由周期 writeback 顺手落盘,再配返回用户态前的节流与 frozen 文件系统保护,ext4 预分配块 inode 作为首个用户
-
DAMON 合并拆分 region 只遍历已安装的 probe
DAMON region 的 probe_hits 数组容量固定为 DAMON_MAX_PROBES(4),合并与拆分 region 时一律遍历整个数组,未装 probe 的空槽位也照算照拷;两个函数收下 context 后改用 damon_for_each_probe() 沿 probe 链表只处理已安装的槽位,消除代码中两条 todo 指认的冗余迭代
-
按地址有序分桶的反碎片 buddy 分配器
把 buddy 的 freelist 按地址划分成多个 bucket,movable 从低地址端、unmovable 与 reclaimable 从高地址端聚簇分配,主动压低外部碎片,把 compaction 与 reclaim 向后推迟;分配侧用 active bucket 与 bucket 级 bitmap 免扫空 bucket,释放侧用 lockless 暂存链表均摊冷链表访问。内核编译实测 compact_stall 从 4000 降到 5,anon_fault_fallback 下降,耗时几乎无回退
-
内核线程与远程 charge 的 memory.high 超限改由 worker 异步回收
把 memory.high 超限处理从 try_charge_memcg 抽成 memcg_enforce_high;内核线程与远程 charge 不再走「记超额、返回用户态回收加节流」的本地路径,改为给被记账层级排 high_work 异步回收,跳过 charge 路径上的同步回收与节流;回收路径上带 PF_MEMALLOC 的 charge 跳过 high 强制,切断 high_work 自我重复排队(zswap 场景无防护实测 163 次)。memory.max 与 swap.max 硬限制不变
-
NUMA 感知回收的自适应多线程 kswapd
每个 NUMA 节点的 kswapd 从单线程扩展为上限 16 的线程池,默认 1 保持现状,唤醒数量按节点空闲核数的 10 秒滑动平均自适应决定,并消除多线程暴露的 multi-gen LRU 并发误警与 hopeless 过早判死,另对只剩两代时的扫描停摆做诊断性放开以验证假设;Cassandra 实测每节点 4 线程吞吐 +10.3%,p99 响应延迟 -48.5%
-
把文件系统的 bdev 缓存按内核文件记账
文件系统使用块设备期间给 bdev mapping 设置 AS_KERNEL_FILE,共享元数据缓存页改记 root memcg,消除 foreign 脏页记录引发的整 wb 提前写回;ext4 测试后台写 I/O -73.3%,前台带宽 +23.0%
-
避免 classic LRU direct reclaim 路径上的过度回收
classic LRU direct reclaim 路径缺少「目标达成」检查,典型 32 页的请求在内存压力下可扫描数万页、释放上千页;给 shrink_lruvec()、shrink_node_memcgs()、should_continue_reclaim() 三处统一加上 max(nr_to_reclaim, compact_gap(order)) 达标退出;Android 20 个最慢事件平均扫描 -83%、平均回收 -96%
-
s390 批量化 lazy MMU 模式下的 PTE 更新
lazy MMU 模式下 s390 PTE 更新攒进 per-CPU 缓存,退出时一次下发,避开逐次 IPTE 的 quiesce,mremap 加速 28 倍
-
批量提交 zswap writeback IO
zswap writeback 每个 entry 单独发一个 IO,reclaim 路径的 swap_io_ctx 批合并机制未被利用;把 swap_io_ctx 所有权上移到 LRU walk 发起者,walk 结束后统一提交,再加 blk plug 让块层合并非连续 entry 的 bio,IO 竞争场景构建时间 -2.9% ~ -3.8%,每个写请求页数 +20%
-
阻止 non-movable 页污染 movable pageblock 以提升 THP 分配成功率
non-movable 页经 claim、steal、compaction capture 三条路径混入 movable pageblock,单个 non-movable 页就毁掉整块 THP 分配且 kcompactd 仍浪费扫描;让 pageblock 类型跟随内容,claim 无条件转换、steal 跳过、capture 整块时转换,THP 分配成功率从 42% 提到 74%,compaction 成功率从 4.7% 提到 92.6%
-
让 defrag_mode 的重试决策跟随 promoted order
defrag_mode 下 non-movable 请求的 reclaim/compaction 已提升到 pageblock_order 运行,但重试决策仍按请求 order 判定,order-0 请求因此无限重试永远到不了 fallback;让重试决策跟随 promoted order,reclaim 空进展不再重置计数器,compaction 按 promoted order 检查结果,fallback 时重置重试预算,should_reclaim_retry 调用从 63M 降到 293k,文件创建快 5.7 倍
-
对不可驱逐的 folio 跳过远程 LRU drain
POSIX_FADV_DONTNEED 驱逐失败时不再一概触发全局 LRU drain:mapping_try_invalidate() 仅对 clean、unmapped、非 writeback 的 folio 失败置 need_drain,mapped、dirty、writeback 的失败不再触发 lru_add_drain_all();32 次 DONTNEED 产生的全局 drain 从 32 次降为 0 次
-
可靠的 1GB gigantic page 分配
让 1GB gigantic page 在数周 uptime 后仍可分配:按固定 1GB gigablock 跟踪不可移动内容,内核分配回退 movable 内存时优先在已混合 gigablock 内有界搜索 claim,纯净范围最后才动用,kcompactd 异步迁出混合 pageblock 中的 movable 页以维持内核 free list;早期原型 22.1 小时 soak 把混合范围从 251/254 压到 33/254,8 个 1GB 页申请全部满足