📅 Linux 内核性能日报 - 2026-08-06

Linux 7.2(7.1 → 7.2-rc6)周期性能优化专题 · 调度器 · 内存 · 分配器 · swap
15
分析篇
0
进展更新
15
新增(Linux 7.2)

📌 专题说明:Linux 7.2 周期性能优化

分析范围:Linux 7.2(v7.1 → v7.2-rc6,08-02 发布 rc6)开发周期
本日报为 Linux 7.2 版本周期性能优化专题。在 v7.1..v7.2-rc6(17086 提交)中按性能路径(sched/mm/block/net/fs/locking)与信号词召回,精排后两波深度分析共 15 篇:第一波 11 篇(调度器缓存感知负载均衡 33 补丁大系列、slab 编译期类型化分区、swap cache 稳定大分配、khugepaged mTHP、arm64 TLB flush、slab bulk gfp、sched proxy try_to_wake_up、cpuidle、fuse readdir、f2fs GC、fscrypt 零分配);第二波补挖 4 篇(io_uring tw_pending、f2fs buffered overwrite 快路径、arm64 DVMSync TLB 批量、sched proxy return-migration)。每个特性均标注主线合入版本(Linux 7.2,git describe --contains 确认),供后续版本级聚合使用。候选清单见 data/7.2-analysis-candidates。

⚡ 调度器

33 补丁大系列(Intel Peter Zijlstra/Chen Yu/Tim Chen),解决 CFS 负载均衡只看 CPU 负载、不看缓存域——把共享工作集的同进程线程摊到不同 LLC,迫使跨片缓存一致性流量放大 LLC miss。核心:追踪每进程×每 CPU 的占用度(epoch 衰减),计算进程优选 LLC,新增 migrate_llc_task 迁移类型,均衡器优先搬偏爱任务。本补丁(df0d9847)为纯基础设施(CONFIG_SCHED_CACHE + mm_struct.sc_stat per-CPU 占用度追踪),机制惰性由后续补丁启用。系列基准(作者自报未独立验证):hackbench Sapphire Rapids 最高 +31.9%、Genoa +47.3%、chacha20 +24%~+48%、schbench 唤醒延迟 +22%。
代理调度(proxy execution,让阻塞在互斥锁上的任务把 CPU 让给锁持有者代为运行)启用时,最热的唤醒路径 try_to_wake_up() 每唤醒一个任务都要额外检查"任务是否还挂在某锁上"。本补丁建立"proxy_deactivate() 前 blocked_on 必为空"的不变量,删除该防御代码——每次唤醒减一个静态分支 + 字段读取,代理阻塞唤醒不再抢锁。仅 CONFIG_SCHED_PROXY_EXEC 生效(非 proxy 内核为死代码)。未提供基准。
在启用代理调度(sched/proxy,一种让"阻塞在互斥锁上的任务"把 CPU 执行权让渡给锁持有者代为运行的调度机制)的内核上,一个被"代理迁移"到别的 CPU 的任务被唤醒时,需要返回迁移回它能运行的 CPU。补丁前这个动作发生在 __schedule() 深处的 proxy_force_return()——它要释放 rq 锁、重新拿 task_rq_lock(含 pi_lock)、重新校验、出队、选核、挂回目标 rq、再重新拿回 rq 锁,一轮锁往返外加一次强制重新选核。本补丁把这个返回迁移前移进 try_to_wake_up():唤醒路径发现任务被代理迁移过,就在已持有的 rq 锁下把它出队,随后的正常唤醒流程(select_task_rq() → ttwu_queue())自然把它放到一个能运行的 CPU 上——整段 proxy_force_return() 连同它的锁往返直接删除。未提供基准。

🧠 内存

Marco Elver(Google)把 RANDOM_KMALLOC_CACHES 重构为通用 KMALLOC_PARTITION_TYPED:利用 Clang 22+ 的 __builtin_infer_alloc_token() 在编译期推断每次 kmalloc 对象类型,token 经宏贯穿 kmalloc/krealloc/kvmalloc,最终作为 16 个分区 slab cache 的确定性下标——把"原始字节缓冲区"与"含指针/关键元数据"对象物理隔离,越界写无法跨分区污染指针对象。补丁未提供吞吐/延迟基准(作者自报"以相对较低性能代价实现"),/proc/slabinfo 分布为作者自报(08-15 区 12015 个含指针对象)。
Kairui Song(腾讯)swap-table 系列(v5,12 补丁)第 4 个:重写 swap_cache_alloc_folio()(新增 orders 位图 + vmf 参数),在 swap cache 层统一"槽位检查→分配→插入"。核心 __swap_cache_alloc() 双重检查:cluster 锁下①检查范围→解锁分配页→②持同一锁复检+原子插入,杜绝旧版"无锁冲突检查"的假阴性窗口(大 folio 分配后插入冲突、整段解卷回退);orders 位图支持 -EBUSY/-ENOMEM 降阶重试。为系列第 5 补丁"unify large folio allocation"提供前提。补丁未提供基准(基础设施),收益为逻辑分析(解读(AI 分析))。
khugepaged 以前只能折叠整块 2MB PMD 巨页,"有空洞"区间(数据库索引/稀疏 mmap/按需分配的虚拟机内存)只要空页超阈值就整块放弃。本补丁扫描阶段把占用 PTE 记入位图,折叠阶段按位图贪心选最优 mTHP 阶数(16K~1MB)按需折叠——减少 page fault 与 TLB miss。补丁未提供基准,收益为逻辑分析。
内存热移除拆 vmemmap 时,此前被改成按块大小(2MB/1GB)刷 TLB——非 FEAT_TLBIRANGE(ARMv8.4+)的 CPU 上 2MB 块=512 页正好触发退化全 TLB 广播,大容量热移除时形成跨核广播风暴。本补丁把块级映射失效收窄回单页(块映射在 TLB 只占一条,失效单页即可逐出),保留批量刷收益。未提供基准(被修 commit 自报 2GB 热移除耗时降 97%)。
批量分配(网络收包 NAPI skb 缓存、io_uring 请求)的 kmem_cache_alloc_bulk() 此前按调用者 gfp 标志决定"能否在 per-NUMA barn 锁上自旋"——GFP_ATOMIC 在锁争用时走 trylock 快速失败掉回更贵的 slab 页慢路径。本补丁统一自旋等锁,快速路径命中率更高。slab_alloc_flags 系列(v2 16 补丁)收尾。未提供基准。
在带 C1-Pro SME DVMSync erratum(ARM64_ERRATUM_4193714)的 Arm 服务器上,上一版 erratum workaround(0baba94a9779)在页面回收(kswapd)的批量 TLB 刷路径里,为了安全采样 mm_cpumask() 给每一次批量都硬加了一次 dsb(ish) 屏障,把"多页凑一批、只同步一次"的批量收益打散,合入说明指出造成 kswapd 约 30% 性能回归(数据来自 arm64-fixes 合并请求摘要,未独立验证)。本补丁改用全局 sme_active_cpus 掩码(跟踪哪些 CPU 正以 SME 用户态运行)替代逐 mm 的 cpumask 采样:批量刷完成时直接对该掩码发一次 IPI,删掉每次批量的 DSB、每任务 cpumask 分配与相关生命周期管理(净删 87 行),恢复批量收益、修复该回归。

🔌 电源

2025-11 误加的"sanity check"要求空闲态 exit_latency 必须 ≤ target_residency,否则驱动注册失败(有现场系统因此整个 cpuidle 失效)。作者确认 menu governor 把两者当独立约束(target_residency 只对预测空闲时长、exit_latency 只对 PM QoS 延迟需求),从不互比——彻底删除该检查,更深空闲态可正常进入,减少唤醒与能耗。未提供基准。

💾 I/O

在常规(非 DEFER_TASKRUN)io_uring 高吞吐负载下,普通 task_work 的 mpscq 队列在一次运行中会多次经历"空→非空"切换,旧实现用一个 per-tctx 的 tw_pending 原子位来守卫"回调只挂入内核 task_work 链表一次";本 commit 把运行策略改为"队列一空就停"(用新增的 mpscq_pop_emptied() 判断并 break),从而移除该守卫位,连同它在入队热路径上的原子位操作和每次运行开头的内存屏障一起删掉。补丁未提供基准数据,属于 mpscq 重构系列的收尾清理 + 热路径微优化。

📁 文件系统

virtiofs 上 overlayfs 大目录未缓存 readdir 时,多 MB 输出缓冲被整块拷进 kmalloc(GFP_ATOMIC) 的 argbuf——需要大块连续物理内存的原子分配,内存压力下易 -ENOMEM 中断遍历。本补丁改用 alloc_pages_bulk() 离散页,virtiofs 作为 scatter-gather 条目直接入 virtqueue,DMA 直达各页——消除大块连续原子分配 + 整块 memcpy。未提供基准。
大 section 模式下 GC 从 section 首段读 SIT 类型作代表类型;SPO 掉电恢复后首段变空但残留旧 NODE 类型,后续有效段校验误报 "Inconsistent segment type" → 挂载失败。本补丁把代表类型判定挪进主循环(由实际有数据的段决定),消除假 panic。正确性修复,非吞吐提升。
内联加密(blk-crypto)三条热路径(选实现/准备/销毁 key)每次调用都动态分配设备列表数组再 kfree。本补丁改为栈上数组(FSCRYPT_MAX_DEVICES=8),单设备快路径零分配——每次少一次 kmalloc+kfree+IS_ERR 分支,且消除回收上下文里的 GFP_KERNEL 分配(顺带修了 UAF:撤销 key 时分配失败跳过错略导致 keyslot 悬垂)。未提供基准。
在"已有数据块的逻辑→物理映射已被 f2fs 内存中的读 extent 缓存记录"的覆盖写(buffered overwrite)场景下,f2fs 每次写都先取 inode folio(dnode 节点页)再查缓存,多付一次节点 folio 查询(页缓存 xarray 查找 + 锁 + inode 校验和 + sanity 检查)的固定开销;本补丁把"查读 extent 缓存"提前到取 inode folio 之前,缓存命中即直接返回块地址、整体跳过节点 folio 查询。作者在 QEMU/KASAN x86_64 VM 中测得 64 字节覆盖写中位耗时 1724.93 → 1560.24 ns/write(约 -9.6%)、256 字节覆盖写 1713.38 → 1577.85 ns/write(约 -7.9%),20k 次写中 f2fs_get_inode_folio() 调用从 20004 降到 4(作者自报,未独立验证)。
⚠️ 免责声明

本站内容均由 AI 基于公开知识辅助生成,仅供学习参考,请勿直接引用作为依据。作者不对信息的准确性、完整性及适用性作保证,亦不对因使用本站内容产生的任何损失承担责任。