当前位置:首页>Linux>Linux mm 2026-04-21 最新 Feature 分析报告

Linux mm 2026-04-21 最新 Feature 分析报告

  • 2026-07-04 02:41:52
Linux mm 2026-04-21 最新 Feature 分析报告
目录
  1. zsmalloc 异步延迟释放:降低 Android LMK 路径上的 swap 释放延迟
  2. zone 连续性检查的增量维护:加速大内存 VM 的 hotplug/unplug
  3. 批量页清零:在 init_on_alloc 路径下绕过 per-page kmap 开销
  4. Swap Table Phase IV:统一分配与静态元数据精简
  5. cgroup 驱动的 swap tier 选择
  6. alloc_tag 早期 PFN 追踪:从固定数组到动态链表
  7. page_alloc: 修复 init_on_free 下 huge zero folio 的 MTE tag 泄漏
  8. SLUB refill 路径的乐观 freelist 归还快路径
  9. kmemleak verbose 输出按 backtrace 去重
  10. process_mrelease:加速 clean file folio 回收 + 引入 auto-kill
  11. virtio:跳过 host 已清零 reported pages 的冗余清零

1. zsmalloc 异步延迟释放:降低 Android LMK 路径上的 swap 释放延迟

系列[RFC PATCH v2 0/4] mm/zsmalloc: reduce zs_free() latency on swap release path作者: Wenchao Hao,Xueyuan Chen、Barry Song版本: v2(4 个 patch)

背景

在 Android 等内存受限场景中,Low Memory Killer(LMK)会集中杀掉多个进程以回收内存。进程退出时需要解除 VMA 中大量 swap 条目的引用,而其中每一条 swap 条目都会穿过 zram 的 zram_slot_free_notify() 路径调用 slot_free(),最终由 zs_free() 释放 zsmalloc 句柄。作者在分析中发现,slot_free() 成本的 80%~87% 花在 zs_free() 上——因为它既要获取 pool->lockclass->lock,也可能在 zspage 引用计数归零时把整个 zspage 还给 buddy(需再抢 zone lock)。这条慢路径把"匿名 folio 释放"也拖慢了,直接影响系统回收速度。社区此前 Justin Jiang 和 Lei 的两版 RFC(2024/2025)尝试在 mm 核心引入独立线程异步回收,但架构复杂且侵入性大;Barry Song 最近 RFC 则从 zram 层单独尝试异步释放。本系列综合了上述思路,把优化下沉到 zsmalloc 层,使得 zram 与 zswap 都能受益。

解决的问题

  • zs_free() 在 class->lock 保护下调用 __free_zspage() 把页归还 buddy,期间会等 zone lock,导致同一 class->lock 被长时间持有,阻塞其他 CPU 的 zs_free()
  • 进程退出路径上的 zram_slot_free_notify() 和 zswap_invalidate() 同步执行 zs_free(),延迟匿名 folio 的整体释放,恶化 LMK 场景下的回收速率。
  • 现有 slot_free() 把"slot metadata 清理"与"zsmalloc 句柄释放"耦合在一起,难以独立推迟后者。

如何做

系列采用两条互补路径。第一条是压缩锁窗口(patch 1):把 __free_zspage() 中实际把页归还 buddy 的逻辑拆成 __free_zspage_lockless()zs_free() 在 class->lock 内只做 remove_zspage() 和 class_stat_sub(),随后先 spin_unlock(&class->lock) 再调用 __free_zspage_lockless() 归还页面,避免 zone lock 等待污染 class 锁。若 trylock_zspage 失败则退回 kick_deferred_free()

第二条是异步延迟释放(patch 2):新增 zs_free_deferred()/zs_free_deferred_flush() 两个 API。在 struct zs_pool 中加入一块固定大小的 handle 环形区:

#define ZS_DEFERRED_FREE_MAX_BYTES  (128 << 20)
#define ZS_DEFERRED_FREE_CAPACITY (ZS_DEFERRED_FREE_MAX_BYTES >> PAGE_SHIFT)
#define ZS_DEFERRED_FREE_THRESHOLD (ZS_DEFERRED_FREE_CAPACITY / 2)

容量按 128MB 未压缩数据预算计算,随 PAGE_SIZE 自然缩放。zs_free_deferred() 使用 spin_trylock() 入队,队列满或锁争用时 fallback 到同步 zs_free();达到阈值时 queue_work(system_wq, &pool->deferred_free_work)。Pool 销毁前 zs_free_deferred_flush() 保证 drain。

第三、四条是使用者改造:patch 3 将 zram 的 slot_free() 拆成 slot_free_extract()(只做 metadata 清理并返回 handle)和外部的 zs_free()zram_slot_free_notify() 把 handle 交给 zs_free_deferred();其他同步路径(write/discard/meta_free)保持不变。Patch 4 对 zswap 做类似改造,把 zswap_entry_free() 封装成 __zswap_entry_free(entry, deferred),仅 zswap_invalidate() 走延迟路径,load/writeback/store 错误路径仍用同步释放。

收益

场景
基线
优化后
提速
RADXA O6,12 CPU 并发 zs_free()(patch 1 压缩锁窗口)
-
-
执行时间减少 20%
RK3588 unmap 256MB swap-filled VMA(pin CPU2)
63,102,982 ns
18,570,726 ns
3.4x
RK3588 swap-in 256MB(pattern 填充,副作用改善)
1,358,133,886 ns
1,104,315,986 ns
1.22x

作者原话:"slot_free() accounting for more than 80% of the total cost of freeing swap entries",延迟释放同时让 do_swap_page() 不再等待 slot_free 完成,这是一个有益的副作用。


2. zone 连续性检查的增量维护:加速大内存 VM 的 hotplug/unplug

系列[PATCH v4 0/2] mm/memory hotplug/unplug: Optimize zone contiguous check when changing pfn range作者: Yuan Liu,Tianyou Li版本: v4(2 个 patch)

背景

zone->contiguous 是 mm 的一个优化位:当为真时 pageblock_pfn_to_page() 可直接 pfn_to_page() 而无需 pfn_valid()/__pageblock_pfn_to_page() 逐 pageblock 验证,显著降低 compaction、isolation 等热路径开销。但它是一个"all-or-nothing"属性:只要 zone span 内出现任意一个未初始化的 memmap hole,就必须清零;反过来要置位则需要线性扫描整条 zone。在 move_pfn_range_to_zone() 和 remove_pfn_range_from_zone() 两条 hotplug 路径上,当前实现每次调整一段 pfn 范围都要 clear_zone_contiguous() + set_zone_contiguous(),后者的扫描成本随 zone 大小线性增长。在大内存 VM(几百 GB)或 CXL 设备热插拔场景下,这个扫描动作成为瓶颈——作者报告 256GB 插入需 10s、512GB 需 36s,且很大部分消耗在 set_zone_contiguous()。同时 v4 新增 patch 1 清理了 overlap_memmap_init() 的设计缺陷:该检查原本嵌在 memmap_init_range() 的热循环里逐 pfn 判断 mirrored kernelcore 重叠,实际上应提到更外层的 memmap_init() 做粗粒度跳过。

解决的问题

  • set_zone_contiguous() 对几百 GB 的 zone 进行全量 pageblock 扫描,hotplug/unplug 延迟随 zone 规模线性恶化。
  • overlap_memmap_init() 作为静态函数在 memmap_init_range 的 PFN 热循环中被调用,既污染热路径又结构割裂。
  • 现有 zone->contiguous 缺少可增量维护的计数器,无法快速判断 zone span 内 memmap 是否仍然完整。

如何做

整体思路是把连续性判定从"全量扫描"换成"增量计数":为 zone 新增 pages_with_online_memmap 计数器,跟踪 zone span 内已有 online memmap 的页数(包括 present 页和已经通过 init_unavailable_range() 初始化的 hole)。核心不变式:

staticinlinevoidset_zone_contiguous(struct zone *zone)
{
if (zone_is_zone_device(zone))
return;
if (zone->spanned_pages == zone->pages_with_online_memmap)
        zone->contiguous = true;
}

即只要 spanned_pages == pages_with_online_memmap,zone 即为 contiguous。该 helper 连同 zone_is_contiguous()clear_zone_contiguous() 一并移到 include/linux/mmzone.h inline,取代原来 mm/mm_init.c 中的 O(N) 扫描版本。

计数器的维护点遍布 hotplug 生命周期:memmap_init_zone_range() 为每段新初始化的 present 区域累加 end_pfn - start_pfninit_unavailable_range() 改为返回实际初始化的 hole 页数,也累加到 pages_with_online_memmap(并先把 hole_pfn 截断到 zone_start_pfn 以避免跨 zone 误计);adjust_present_page_count() 在 online/offline 时同步更新计数。调用位置也从 move_pfn_range_to_zone()/remove_pfn_range_from_zone() 内部移到 drivers/base/memory.c 的 memory_block_online()/memory_block_offline(),让一整个 memory block 的多次 span 调整共享一次 clear/set 对。另一条独立的清理:把 mirrored_kernelcore 重叠判断从 memmap_init_range() 的 PFN 热循环上移到 memmap_init() 的 region 级循环,热路径更干净。

收益

操作
规模
基线
优化后
缩减
Plug Memory
256G
10s
3s
70%
Plug Memory
512G
36s
7s
81%
Unplug Memory
256G
11s
4s
64%
Unplug Memory
512G
36s
9s
75%

测试环境为 Intel Icelake server + QEMU 9.0 + v7.0-rc4 Guest kernel,通过 virtio-mem-pci 触发 hotplug,measure 的是从 QEMU 下发命令到 Guest /proc/meminfo MemTotal 反映新内存的总时间。系列已收到 Tim Chen、Qiuxu Zhuo、Yu C Chen、Pan Deng、Nanhai Zou 的 Reviewed-by,CXL 热插拔场景亦有独立验证链接。


4. 批量页清零:在 init_on_alloc 路径下绕过 per-page kmap 开销

系列[PATCH v2] mm/page_alloc: use batch page clearing in kernel_init_pages()作者: Hrushikesh Salunke版本: v2(单 patch)

背景

init_on_alloc=1 是一项安全加固特性:page allocator 在返回页面前把它们清零,防止敏感数据泄露到下一次分配。它的核心路径是 kernel_init_pages(),对一次 __alloc_pages 返回的 numpages 个连续页逐个调用 clear_highpage_kasan_tagged()。每一次 clear_highpage_kasan_tagged() 都做两件事:kmap_local_page() 建立临时映射、清零完 kunmap_local()。在 !HIGHMEM 的 64-bit 架构上 kmap_local_page() 本质是简单的 page_address(),但函数调用、栈帧、KASAN tag reset 等开销仍然按页累加;更重要的是,清零动作被打碎成一页一页的 memset,阻止了架构级优化原语(例如 x86 的 REP STOSB、ARM64 的 dc zva、非时序写入 movnt 等)对大段连续物理内存一次性发射的机会。在 HugeTLB、大型 Graph500/Pagerank 工作负载中,init_on_alloc 的纯清零成本因此被放大。作者观察到分配 16GB HugeTLB 时清零本身就占用近 0.45s,是个明显可优化点。

解决的问题

  • kernel_init_pages() 的 per-page loop 产生 numpages 次 kmap_local_page/kunmap_local 往返和函数调用,额外开销随 numpages 线性放大。
  • 逐页 memset 无法让 CPU 的批量清零/非时序存指令跨页面连续发射,浪费硬件的大块写带宽。
  • 需要保留 HIGHMEM(32-bit)的正确性——其页面必须先 kmap 才能写入。

如何做

在 include/linux/highmem.h 新增 helper clear_highpages_kasan_tagged(),把 HIGHMEM 与 !HIGHMEM 分派清晰化(v2 根据 David 的建议从 page_alloc.c 提炼到 highmem.h):

staticinlinevoidclear_highpages_kasan_tagged(struct page *page, int numpages)
{
if (!IS_ENABLED(CONFIG_HIGHMEM)) {
        clear_pages(kasan_reset_tag(page_address(page)), numpages);
    } else {
int i;
for (i = 0; i < numpages; i++)
            clear_highpage_kasan_tagged(page + i);
    }
}

在 !HIGHMEM 分支上,先一次 page_address(page) 取得连续线性地址起点,一次 kasan_reset_tag() 去标签,然后单次 clear_pages() 覆盖整段 numpages * PAGE_SIZE,由架构侧的 clear_pages 实现(如 x86 clear_page_rep/clear_page_erms)统一发射最优指令序列。HIGHMEM 分支保留原来的 per-page 逻辑,确保 32-bit 正确。mm/page_alloc.c 里的 kernel_init_pages() 则删除显式 for 循环,只剩 kasan_disable_current(); clear_highpages_kasan_tagged(page, numpages); kasan_enable_current(); 三行。值得注意的是 v2 相比 v1 专门撤掉了 cond_resched() 与分批机制:作者在回信中解释 "kernel_init_pages() runs inside the page allocator and can be called from atomic context, making cond_resched() unsafe"。

收益

工作负载
配置
基线
优化后
变化
分配 8192 × 2MB HugeTLB(共 16GB)
init_on_alloc=1
0.445s
0.166s
-62.7%(2.68x)
Graph500
64C128T,kernel time
30m 41.8s
15m 14.8s
-50.3%
Graph500
16C32T,kernel time
15m 56.7s
9m 43.7s
-39.0%
Pagerank
32T,kernel time
1m 58.5s
1m 12.8s
-38.5%
Pagerank
128T,kernel time
2m 36.3s
1m 40.4s
-35.7%

6. swap table phase IV:统一分配与静态元数据精简

系列[PATCH v3 00/12] mm, swap: swap table phase IV: unify allocation and reduce static metadata作者: Kairui Song版本: v3(12 个 patch)

背景

这是 Kairui Song 推动的 swap 子系统重构第 IV 阶段(前三个阶段已合入 mm 树),目标是把长期以来 per-swap_info_struct 的多张"静态元数据数组"全部下沉到动态分配的 swap cluster table,使 swap 设备开销逼近零。历史上 swap 有若干并列的元信息:swap_map(引用计数)、zeromap(zero-filled page 位图)、swap_cgroup 数组(memcg id 映射)、cached swap cache。这些数组按整盘大小静态分配,一块 1TB swap 设备需要数百 MB RAM 即使完全未使用。同时 anon 与 shmem 两条 swap in/out 路径长期各自实现大 folio 分配、memcg 充值、swap cache 插入,造成代码重复且同步边界不清。Phase IV 之前的 phase 已把 swap map 放进按需分配的 cluster table,本系列则把剩余的元数据(zeromap、swap cgroup id、memcg 关联)也合并进去,并且统一 anon / shmem 的 swap in 分配与充值路径。

解决的问题

如何做

整体思路是把"每张外部 map"折叠进 per-cluster swap_table,并统一 anon/shmem 的 swap in 流水线。首先抽取 __swap_cache_prepare_and_add/__swap_cache_del_folio 通用 helper,新增 add_to_swap_cache_stable 等接口支持直接落位大 folio,THP gfp 辅助函数上移到头文件供 swap 路径复用;再把 anon 与 shmem 的大 folio swap in 分配合并成单一分配器,把 memcg 查找推迟到 folio 已进入 swap cache 后集中处理,并支持把不同 memcg 的 slots 批量释放。其次把 swap_table_alloc/free 改造为 swap_cluster_alloc_table/free_table 的集中接口,然后在每个 cluster 额外挂一张 1024/512 字节的 per-cluster memcg id 表,读写全在 cluster 锁下进行故无需 RCU;整盘 swap_cgroup_ctrl[MAX_SWAPFILES] 全局数组与 mm/swap_cgroup.c(-234 行)整体删除。最后在 swap table entry flags 中多挤出一位存 zero-filled 标记,__swap_table_set_zero/__swap_table_test_zero 取代 set_bit(offset, sis->zeromap);对 entry 位宽不够的 32 位架构,保留一个条件编译的 per-cluster zeromap 字段回退。改动后 struct swap_info_struct 去掉 unsigned long *zeromap,per-slot 静态开销从 ~2 字节降到 ~0.09375 字节(仅每 cluster 48 字节 ci info / 512 slot)。

收益

作者给出了多个负载数据:

测试
环境
Before
After
变化
静态内存开销
1TB swap 设备
used 805MB
used 277MB
-512MB(~0 静态开销)
Redis GET
1.5G VM + 5G ZRAM,redis-benchmark -c 12 -P 32 -t get
3,289,011 RPS
3,312,087 RPS
+0.99%
kernel build
48c96t,8G 内存上限 + 12G ZRAM,make -j96 THP on
user 2904.59s / sys 4773.99s
user 2909.38s / sys 4641.55s
sys -2.77%
usemem
32c + 48G brd ramdisk + 16G RAM,-n 48 1G
6482.58 MB/s,free lat 371371us
6539.28 MB/s,free lat 363059us
吞吐微升,延迟 -2.2%
稳定性
stress test 下 VM_FAULT_OOM leaked 计数
18
0
彻底消除

作者原文结论:"The static metadata overhead is now close to zero, and workload performance is slightly improved."


7. cgroup 驱动的 swap tier 选择

系列[PATCH v6 0/4] mm/swap, memcg: Introduce swap tiers for cgroup based swap control作者: Youngjun Park版本: v6(4 个 patch)

背景

由 Chris Li 建议的特性,目标是让系统里不同速度的 swap 设备(NVMe、SATA SSD、HDD、NBD/Network swap、zswap 后端)能被显式地分组,再让每个 memcg 选择自己允许 swap 到哪一组。现有机制只能给每个 swap 设备赋一个 priority(plist 顺序),然后 "highest priority first",无法按业务隔离——延迟敏感应用可能被迫换出到慢速设备,或者闪存 wear 无法按工作负载切分。LG 自己的部署场景(移动/嵌入式平台)里存在按冷/热 app 分流、按 VM 分流等需求。社区此前讨论过 BPF-based 的 swap device 选择,作者在 Part 2 的设计阐述里明确论证了:BPF 方案 "operate outside the memcg tree",容易与父 memcg 的约束冲突、在受限/嵌入式系统里不适合做核心 swap 行为,选择把控制面绑在 memcg 上更能复用 swap.max/zswap.writeback 等已有 hierarchy 语义。v6 相比 v5 主要是吸收 Sashiko AI review 与 syzbot CI 的修复。

解决的问题

  • 无法按 memcg 选择 swap 设备,导致 latency-sensitive 与 background 负载共享慢速 swap 带来尾延迟。
  • 闪存设备无法按 cgroup 隔离写入,wear-leveling 不可控。
  • Chris Li 的 per-VM 场景:job 可用 zswap + SSD,但 guest memory 要限定到 SSD。
  • 没有一个可扩展的抽象层将来接 per-tier queue、promotion/demotion、madvise hint。

如何做

实现分四层。第一层 mm/swap_tier.c/.h 引入 tier 基础设施:tier 是"按 priority 连续区间 + 用户命名"的分组,覆盖整个 DEF_SWAP_PRIO(-1) 到 SHRT_MAX 的 priority 空间。新增 CONFIG_NR_SWAP_TIERS(默认 4,范围 1–31)。接口为 /sys/kernel/mm/swap/tiers,写入语法 +name:prio 添加、-name 删除,支持单次 batch 输入:解析器左到右执行,先 swap_tiers_snapshot() 再逐 token 应用,任一步失败就 swap_tiers_snapshot_restore() 回滚;添加时按起始 priority 分裂/合并区间,合并方向向低位扩展以保留用户配置的起始值。第二层把 swap 设备挂接到 tier:struct swap_info_struct 新增 tier_maskswapon 时根据设备 priority 匹配已配置 tier 区间;tier 的动态分裂/合并约束必须不改变已激活设备的归属。第三层是 memcg 接口:struct mem_cgroup 新增 tier_mask 与 tier_effective_maskREAD_ONCE/WRITE_ONCE 保护),并提供 memory.swap.tiers(读写,(+|-)TIER 语法)与 memory.swap.tiers.effective(只读,父 effective 与自身配置的交集);tier 继承 swap_tiers_memcg_inherit_mask() 推迟到 css_online(),关闭早期创建竞态窗口。第四层让 swap allocator 按 tier 过滤:swap_alloc_fast 取 folio_tier_effective_mask(folio) 与 percpu 缓存 si 的 tier_mask 比较,不匹配就落到 slow path;swap_alloc_slow 在 plist_for_each_entry_safe(si, ..., &swap_avail_head) 时用 swap_tiers_mask_test(si->tier_mask, mask) 跳过不合规设备。作者坦承存在两项已知限制,将在后续 per-tier swap_active_head 与 fast/slow path 优化中再解决。

收益

场景
指标
Before
After
变化
App A 冷启动
首次启动耗时
13.17s
4.18s
-68%
App B 冷启动
首次启动耗时
5.60s
1.12s
-80%
App C 冷启动
首次启动耗时
10.25s
2.00s
-80%
未配置 tier
kernel build / vm-scalability
baseline
-
<1% 回归(RFC v2 实测)

测试环境为 LG 内部平台,用 NBD 作为独立 tier。该接口也为将来 intra-tier 分配策略、inter-tier promotion/demotion、MADV_SWAP_TIER 等演进铺好抽象底座。


10. alloc_tag 早期 PFN 追踪:从固定数组到动态链表

系列[PATCH v2] mm/alloc_tag: replace fixed-size early PFN array with dynamic linked list作者: Hao Ge版本: v2(1 个 patch)

背景

Memory allocation profiling(CONFIG_MEM_ALLOC_PROFILING)通过为每个分配点关联一个 alloc_tag/codetag,把内存计数归属到源代码调用位置。该机制依赖 page_ext 保存每个 page 的 codetag ref,但在 boot 早期,page_ext 尚未初始化时已经发生了相当数量的 page 分配(例如 smp_init 期间 CPU hotplug 回调分配的 trace ring buffer、scheduler per-CPU 数据等)。这些 page 的 codetag ref 保持未初始化;当它们日后被释放时,alloc_tag_sub_check() 会触发 "alloc_tag was not set" 的 WARN。为了解决这个问题,现有代码用 clear_early_alloc_pfn_tag_refs() 在 page_ext 就绪后把这些早期 PFN 的 ref 显式清成 CODETAG_EMPTY。实现上,历史方案使用一个固定大小 EARLY_ALLOC_PFN_MAX = 8192 的 __initdata 数组 early_pfns[] 追踪这些 PFN,超出则 pr_warn_once 丢弃。原有注释已经留下 TODO:「Replace fixed-size array with dynamic allocation using a GFP flag similar to ___GFP_NO_OBJ_EXT to avoid recursion」。

解决的问题

  • 固定大小 8192 不可扩展:早期分配数量与 CPU 数目正相关,在大 CPU 机器上可能超出上限导致追踪丢失,进而产生虚假 WARN。
  • 单纯改成运行时 alloc_page() 会造成递归:alloc_page() → post_alloc_hook() → pgalloc_tag_add() → __pgalloc_tag_add() → alloc_tag_add_early_pfn() → alloc_page() → ...,无限递归。
  • v1 到 v2 的修复:并发下追加 early_pfn_pages 链可能丢页(leak),GFP_ATOMIC 在进程上下文里是无谓的收紧。

如何做

核心思路是把固定数组替换成"slab of nodes"式的动态链表,并通过一个新 GFP 标志打断递归。数据结构:

structearly_pfn_node {structearly_pfn_node *next;unsignedlong pfn; };
#define NODES_PER_PAGE (PAGE_SIZE / sizeof(struct early_pfn_node))
staticstructearly_pfn_node *early_pfn_list;/* 已记录 PFN 的链表 */
staticstructearly_pfn_node *early_pfn_freelist;/* 空闲 node freelist */
staticstructpage *early_pfn_pages;/* 所有承载 node 的 page 链 */

alloc_early_pfn_node() 优先从 freelist 取空闲 node;若耗尽,则调用 alloc_page(gfp | __GFP_NO_CODETAG | __GFP_ZERO) 申请一页,按 NODES_PER_PAGE 切分:第 0 个 node 立即返回给调用者,其余 NODES_PER_PAGE - 1 个 node 用 cmpxchg 原子链入 freelist,page 自身则通过 page->private 串成 early_pfn_pages 链供最终回收。

打断递归的关键是新 flag __GFP_NO_CODETAG,它复用了 __GFP_NO_OBJ_EXT 这一 bit。pgalloc_tag_add() 的签名被扩展携带 gfp_t gfp_flags__pgalloc_tag_add() 中通过 should_record_early_pfn(gfp_flags) 判断;alloc_tag 自身为了追踪而分配的 page 带上该 flag,__pgalloc_tag_add() 就直接 return,避免再次进入 alloc_tag_add_early_pfn()

v2 的并发修正:early_pfn_pages 链的更新改用 cmpxchg 循环;同时根据 gfpflags_allow_blocking(gfp_flags) 选择 GFP_KERNEL vs GFP_ATOMIC,避免进程上下文里无谓地 pin 成 atomic。clear_early_alloc_pfn_tag_refs() 扫完 early_pfn_list 后,额外遍历 early_pfn_pages 对承载 node 的 page 本身 clear_page_tag_ref() 并 __free_page() 释放,整个基础设施干净消失,不残留 init 内存。

收益

作者未提供性能数据,从代码逻辑推断的预期收益:消除了大 CPU / 大内存机器上因早期分配超过 8192 条而丢失追踪的"alloc_tag was not set" WARN 噪声,使 alloc tagging 调试在任意规模机器上都具备正确性;由于整个结构仅在 __initdata 路径活跃、在 page_ext 就绪后即被释放,运行时零开销;cmpxchg lock-free 链表也避免了在并发早期分配路径上引入新锁。


12. page_alloc: 修复 init_on_free 下 huge zero folio 的 MTE tag 泄漏

系列[PATCH v2] mm/page_alloc: fix initialization of tags of the huge zero folio with init_on_free作者: David Hildenbrand版本: v2(1 个 patch)

背景

Arm MTE(Memory Tagging Extension)在内核中依赖 __GFP_ZEROTAGS flag 把分配时的 tag memory 也一并清零。此前该 flag 与 __GFP_ZERO 语义紧密耦合:在 post_alloc_hook() 中,只有当内核确定要对页面 payload 做 zero init(即 init=true)时,才会把 zero_tags 也置为 true 并调用 tag_clear_highpages()。在通常路径下这是正确的——set_pte_at() 在第一次把页面映射到用户空间时会检测到 PG_mte_tagged 未设置,由其完成 tag 初始化。但 huge zero folio 是一个显著例外:它通过一个 special 标记的 PMD 被映射(大量 VMA 共享同一张只读零页),并不会走 per-page 的 set_pte_at() tag 初始化路径。于是 Documentation/arch/arm64/memory-tagging-extension.rst 中 "allocation tags are set to 0 when a page is first mapped to user space" 的约定被打破。作者通过修改 arm64 check_buffer_fill MTE selftest,改用 2 MiB 区域复现(测试 17 / 18 fails),定位到根因。

解决的问题

  • 当 init_on_free=1 时,页面是在 __free_pages_prepare() 阶段被清零的,分配时 init=false,导致 zero_tags 被短路为 false,tag 根本没被清。
  • huge zero folio 因不走 set_pte_at tag init 路径,上述遗漏会把陈旧 tag 直接暴露给用户态,属于信息泄漏与行为规范违反。
  • tag_clear_highpages() 返回值语义"是否完成了页面清零"反直觉,易读错。

如何做

核心是把 __GFP_ZEROTAGS 与 __GFP_ZERO 解耦,并让 tag_clear_highpages() 同时承担"仅清 tag"与"tag + payload 一起清"两种模式。接口改为 bool tag_clear_highpages(struct page *to, int numpages, bool clear_pages),返回值倒置为"调用方是否仍需自行初始化页面"。在 arm64 实现里,根据 clear_pages 在 mte_zero_clear_page_tags()(同时清 tag 与 payload)与 mte_clear_page_tags()(仅清 tag)之间选择;在 !system_supports_mte() 的 fallback 下直接返回 clear_pages,把责任还给通用代码。post_alloc_hook() 中则将 zero_tags 改为纯粹由 gfp_flags & __GFP_ZEROTAGS 决定,与 init 解耦:

constbool zero_tags = gfp_flags & __GFP_ZEROTAGS;
...
if (zero_tags)
    init = tag_clear_highpages(page, 1 << order, /* clear_pages= */init);

同时在 gfp_types.h 里重写 __GFP_ZEROTAGS 注释,显式说明这不再是纯优化 flag,而是保证——即使在 init_on_free 场景下——tag 也会被清零。修改覆盖 arch/arm64/include/asm/page.harch/arm64/mm/fault.cinclude/linux/gfp_types.hinclude/linux/highmem.hmm/page_alloc.c 五个文件,共 21 增 17 删。v2 相较 v1 撤回了基于 kasan_hw_tags_enabled() 的分支(会漏掉纯 user MTE 无 KASAN 的场景),并继续保留 system_supports_mte() 检查以确保无 MTE 硬件时 fallback 到通用 clear_highpage()。patch 带有 Cc: stable 标签。

收益

作者未提供性能数据(本系列定位为 bug fix 而非优化)。从代码逻辑推断的预期收益:修复 arm64 在 init_on_free=1 配置下使用 huge zero folio 时的 MTE tag 信息泄漏 / 行为偏差,使 check_buffer_fill selftest 的 "Check initial tags ... mmap memory" 用例重新通过;同时通过解耦 __GFP_ZEROTAGS,为后续继续拆分 __GFP_SKIP_KASAN 的 cleanup 打好基础。该 fix 对运行时无额外开销——只是在 __GFP_ZEROTAGS 出现时多执行了一次本来就该做的 tag 清零动作。


13. SLUB refill 路径的乐观 freelist 归还快路径

系列[PATCH RFC] mm, slab: add an optimistic __slab_try_return_freelist()作者: Vlastimil Babka版本: v1(RFC,1 个 patch)

背景

本 patch 构建在近期合入的 "mm/slub: defer freelist construction until after bulk allocation from a new slab" 之上。SLUB bulk/refill 路径 __refill_objects_node() 会从一个 slab 中通过 get_freelist_nofreeze() 一次性 detach 整条 freelist:该函数将 slab 的 freelist 置空、把 inuse 设为 objects(从 slab 视角看 slab 已"满"),然后把原 freelist 整条交给调用者,调用者按需消费 max 个对象到目标数组 p[] 里。若 freelist 对象数超出 max,剩余那段就必须"还回去"。老代码的做法是:把剩余段当作 detached freelist,走遍一遍链找到尾 object,然后调 __slab_free(s, slab, head, tail, cnt, _RET_IP_)。这条完整 __slab_free 路径要处理 debug、NUMA partial 管理、cmpxchg 竞争回退等诸多一般性场景,而且首先要从冷缓存里 walk 整条剩余 freelist 来定位 tail,代价不低。

解决的问题

  • refill 归还剩余对象必须先 walk 整条剩余 freelist 定位 tail,tail 往往是 cache cold 的。
  • 复用通用 __slab_free() 处理了许多在本场景不可能出现的情形,额外的分支和锁路径成本浪费。
  • 我们刚刚通过 get_freelist_nofreeze() 原子地把 slab 的 freelist 清零,在极短时间窗内 slab 大概率还"看起来是满的"(没有并发 __slab_free() 往里 push),应当利用这个假设。

如何做

新增 __slab_try_return_freelist(s, slab, head, cnt) 走"乐观快路径",只在仅限非 debug cache 的场景使用:

old.freelist = slab->freelist;
old.counters = slab->counters;
if (old.freelist)          /* 并发 free 已经挂过东西,快路径放弃 */
returnfalse;
new.freelist = head;       /* 直接把剩余段整段接回 */
new.counters = old.counters;
new.inuse -= cnt;
/* 拿 n->list_lock,cmpxchg 更新,add_partial(ADD_TO_HEAD),完成 */

关键是:只需要 head 和 cnt完全不需要 tail——因为 slab 的 freelist 当前为空,把 head 设为新 freelist 头、inuse -= cnt 即可,原 freelist 的 NULL 终结符天然充当新 freelist 的尾。slab 从"全满"变成"有 cnt 个空位",因此要无条件挂到 n->partial 的头部(ADD_TO_HEAD),并记账 FREE_ADD_PARTIAL

失败退化:若 old.freelist != NULL(说明另一个 CPU 已经向此 slab __slab_free() 了至少一个对象),或 slab_update_freelist() cmpxchg 失败,函数返回 false;调用方退回原路径,walk 定位 tail 再调 __slab_free(),并累加 REFILL_RETURN_SLOW stat。配套 get_freelist_nofreeze() 改为通过出参 unsigned int *count 返回 old.objects - old.inuse,refill 循环用 count 驱动而不再用 NULL 终结符判断,这样调用 __slab_try_return_freelist() 时直接拿到准确的 cnt。两个新 SLUB_STAT:REFILL_RETURN_FASTREFILL_RETURN_SLOW,作者称已在调试中观察到乐观路径成功率相当高("show to me the optimistic path is indeed successful")。

收益

作者未提供性能数据,这是明确的 RFC——他写道:"it seems like there should be no downsides (in theory...) so please test if it indeed improves things anywhere and then it could be a better baseline before trying anything that comes with tradeoffs"。从代码逻辑推断的预期收益:refill 归还路径在快路径命中时省掉一次完整的剩余 freelist 链 walk(避免 tail 定位的 cache miss),__slab_try_return_freelist() 较 __slab_free() 指令路径更短、分支更少;作为 refill spilling 讨论的"零 trade-off 基线",它希望先吃掉容易摘的低垂果实,再评估那些有代价的后续优化。


14. kmemleak verbose 输出按 backtrace 去重

系列[PATCH 0/2] mm/kmemleak: dedupe verbose scan output作者: Breno Leitao版本: v1(2 个 patch)

背景

kmemleak 是内核内存泄漏检测器:周期性扫描内核数据段和所有已知分配的对象,把未被引用的对象标记为可疑泄漏。在 kmemleak_verbose 模式下(/sys/module/kmemleak/parameters/verbose=1),每一个被判定为 unreferenced 的对象都会以完整格式打印到 dmesg——包括对象头、大小、comm/pid/jiffies、十六进制 dump,以及通过 stackdepot 保存的 16 帧分配栈。作者的动机是:"I am starting to run with kmemleak in verbose enabled in some 'probe points' across the my employers fleet so that suspected leaks land in dmesg without needing a separate read of /sys/kernel/debug/kmemleak"。这样做的副作用是:某些 workload 从单一调用点泄漏成百上千个对象时,dmesg 会被字节级完全相同的 backtrace 淹没——"Hundreds of duplicates per scan are common, drowning out distinct leaks and unrelated kernel messages, while adding no signal beyond the first occurrence"。

解决的问题

  • verbose 模式下同一 allocation site 的大量泄漏以完全一致的 backtrace 刷屏 dmesg,把真正不同的泄漏和其他内核消息淹没。
  • kmemleak 的 object->lock 是 raw spinlock,在其持有期内调用 kmalloc(GFP_ATOMIC) 会取到 n->list_lock 这类更高 wait-context 的锁,被 lockdep 判为非法嵌套。
  • 对象可能被并发释放:stash 的对象指针跨越 rcu_read_unlock() 后必须保证 use-after-free 不发生。
  • 任何去重不能改变可见性承诺:/sys/kernel/debug/kmemleak 与 "N new suspected memory leaks" 计数必须保持不变。

如何做

在 kmemleak_scan() 的 reporting 阶段引入每次 scan 的 dedup xarray,以 stackdepot 的 depot_stack_handle_t trace_handle 作为 key:

structkmemleak_dedup_entry {
structkmemleak_object *object;/* 第一个代表性对象 */
unsignedlong count;              /* 同 backtrace 的泄漏对象总数 */
};

扫描循环中,持有 raw_spin_lock_irq(&object->lock) 时只是读取object->trace_handle 到局部变量,随即释放锁;锁外再调用 dedup_record(&dedup, object, trace_handle)dedup_record() 先 xa_load 查 key:命中就 entry->count++;miss 则 kmalloc(GFP_ATOMIC) 新 entry,并 get_object(object) 增加 use_count 以便跨 RCU 存活,再 xa_insert。若 kmalloc 失败或 xa_insert 冲突,回退到立即打印(保留"每条泄漏都被记录"的语义)。扫描结束后 dedup_flush(&dedup) 遍历 xarray 打印每个代表对象,并在尾部追加一行 ... and N more object(s) with the same backtrace;然后 put_object() 释放引用,kfree entry,xa_erase,xa_destroy。并发正确性的两点关键:xarray 操作与 GFP_ATOMIC kmalloc 必须在 object->lock 外(避免 raw spinlock 下再抓更高 wait-context 的 slab 锁);stash 的对象指针通过 get_object() 提升的引用计数跨 rcu_read_unlock() 保命,dedup_flush() 打印后再 put_object() 释放。

同系列还新增了 tools/testing/selftests/mm/test_kmemleak_dedup.sh:依赖 CONFIG_SAMPLE_KMEMLEAK=m 的 kmemleak-test 模块——该 sample 在单个 kzalloc() 调用点泄漏 10 个 list entry,共享一个 stackdepot trace_handle;脚本启用 verbose、触发两轮 scan,断言 printed < new_leaks

收益

作者未提供定量 benchmark 数据,从代码逻辑和 cover letter 描述可推断的预期收益:封面信原话 "Hundreds of duplicates per scan are common"——在高频泄漏场景,单次 verbose scan 的 dmesg 输出量从 O(泄漏对象数) 降至 O(唯一 backtrace 数),极大减少 printk 对 console 的压制和 ring buffer 的冲刷,让"真正不同"的泄漏不再被一个高频泄漏 flood 掉。selftest 直接用 printed < new_leaks 作为 PASS 条件,典型示例输出 "PASS: kmemleak verbose output deduplicated (11 printed for 61 leaks)"——从 61 行缩到 11 行(~82% 缩减)。因为仅改动 verbose reporting 代码路径、/sys/kernel/debug/kmemleak 内容和 "N new suspected memory leaks" 计数保持原样,对现有 tooling 向后兼容。


15. process_mrelease:加速 clean file folio 回收 + 引入 auto-kill

系列[PATCH v1 0/3] mm: process_mrelease: expedite clean file folio reclaim and add auto-kill作者: Minchan Kim版本: v1(3 个 patch)

背景

process_mrelease(2) 是 Android LMKD 在内存压力下加速回收被杀进程内存的核心 syscall。但现有实现有两个长期痛点。其一:process_mrelease 只 unmap victim 的 VMA,clean file-backed folio 仍躺在 page cache 里,必须等 kswapd 或 direct reclaim 才能真正释放;在 LMKD 场景下这一延迟会逼迫系统多杀几个无辜后台 app 才能腾出足够内存。其二:UAPI 要求用户态先发 SIGKILL,再拿 pidfd 调用 process_mrelease。这构成一个调度竞态——victim 可能在 reaper 被调度前就走完 do_exit → exit_mm 把 task->mm 清空,process_mrelease 于是返回 -ESRCH;而真正的 exit_mmap 会被推迟到 mm_users 归零,Android 里各类 /proc/<pid>/cmdline 读取、async I/O、远端 VM 访问常会让该引用计数长时间挂着,expedited reclaim 彻底失效。本系列建立在此前的 RFC(2026-04-13)之上,依 David Hildenbrand 的反馈做了 API 与语义调整。

解决的问题

  • Clean file-backed folio 在 process_mrelease 后仍占据 page cache,阻塞内存回收。
  • unmap 路径上的 folio_mark_accessed()/LRU 移动对即将释放的独占 file folio 是纯浪费——perf 显示其占 unmap_page_range 55.75%。
  • userspace 发 SIGKILL 与调用 process_mrelease 之间存在不可消除的调度竞态,造成 -ESRCH 与回收被推迟。

如何做

整套方案围绕一个统一旗标 MMF_UNSTABLE 形成闭环:把 free_pages_and_swap_cache() 统一重命名为 free_pages_and_caches() 并迁入 mm/swap.c,使它对 anon 与 file 两路对称:anon folio 走 free_swap_cache(),file folio 在 mm_flags_test(MMF_UNSTABLE, mm) 为真(即由 OOM reaper 驱动)时调用新引入的 free_file_cache(),后者在 folio_trylock() 成功后通过 mapping_evict_folio() 主动把 folio 从 pagecache evict 掉。在 zap_present_folio_ptes() 中加入短路:当 MMF_UNSTABLE && !folio_maybe_mapped_shared(folio) 时跳过 folio_mark_accessed(),避免把即死的独占 file folio 搬来搬去。UAPI 侧引入 flag PROCESS_MRELEASE_REAP_KILL(aliased 到 1 << 0,并加 PROCESS_MRELEASE_VALID_FLAGS 掩码),把 "kill + reap" 合并为一次原子操作;关键做法是 在发 SIGKILL 之前mmget(mm)(不是 mmgrab)——保持 mm_users > 0,阻止 victim 自身的 exit_mmap,让 reaper 在 process_mrelease 上下文里同步、确定地完成回收:

mmget(mm);                                       /* pin mm_users */
task_unlock(p);
ret = kill_pid(task_tgid(task), SIGKILL, 0);
...
__oom_reap_task_mm(mm);
mmput(mm);

task_will_free_mem() 也新增 ignore_exit 参数,在 reap_kill 路径跳过 SIGNAL_GROUP_EXIT 检查。

收益

作者提供了 perf 数据证明 LRU overhead 的存在:

指标
占比/数值
测试环境
unmap_page_range
 中 folio_mark_accessed 占比
55.75%
mmap_exit_test 下的 exit_mm → exit_mmap perf call graph
其中 __folio_batch_add_and_move
48.79%
同上
folio_remove_rmap_ptes
12.94%
同上
page_table_check_clear
9.86%
同上

绝对时延 / LMKD 端到端数据未给出,从代码推断预期收益为:LMKD 场景下单个 victim 的 file-backed 内存可在 reaper 上下文内同步释放,消除 kswapd 依赖与 ESRCH 竞态,减少"多杀"造成的用户可见 app kill。


17. virtio:跳过 host 已清零 reported pages 的冗余清零

系列[PATCH RFC v3 00/19] mm/virtio: skip redundant zeroing of host-zeroed reported pages作者: Michael S. Tsirkin版本: v3 RFC(19 个 patch)

背景

virtio-balloon 的 free page reporting 机制允许 guest 把自己不再使用的 free page 告诉 hypervisor,host 侧通常以 MADV_DONTNEED 等方式回收这些页的 backing memory——这一动作天然要求 host 把页内容置零并使 guest 侧 cache line 失效。问题在于,当 guest 随后重新 allocate 这些页并把它们交给用户态时,内核又会零一遍(kernel_init_pages()clear_user_highpage() 或 folio_zero_user()),这是一次彻底冗余的 2 MB 级别 memset。更糟的是,在 VIPT 等 aliasing cache 架构上 + init_on_alloc=1 配置下,用户页会被 双重 清零一次:先 post_alloc_hook 里的 kernel_init_pages(),再在 callsite 由 user_alloc_needs_zeroing() 触发一次 clear_user_highpage()。本 RFC 一次性解决两类问题:(a)在 mm core 把用户页零清统一进 post_alloc_hook;(b)通过 PG_zeroed / HPG_zeroed 两个 flag 把 "host 已零"的信息从 page reporting 一直传播到 buddy 分配路径的消费端。

解决的问题

  • 冗余 zero:host 已 zero 的 free page 被 guest 再 zero 一次,开销随 THP 或 hugetlb surplus 分配规模线性放大。
  • aliasing cache 架构上的 user 页双重 zero(upstream bug)。
  • 现有 user_alloc_needs_zeroing() 语义使 callsite 和 allocator 互相不信任对方是否 zero 过。
  • hugetlb 池页在 buddy 分配完很久后才被映射给 user,PG_zeroed(消费于 allocation 时)无法跟踪其状态。

如何做

方案由两部分交织组成。MM core 侧把用户 fault 地址 user_addr 通过 struct alloc_context 从 vma_alloc_folio() 一路贯穿到 post_alloc_hook()__alloc_pages__folio_allocfolio_alloc_mpol__alloc_frozen_pages 公开 API 全部获得新参数,引入 USER_ADDR_NONE 哨兵值);把 prep_compound_page() 前移到 post_alloc_hook() 之前(否则 folio_nr_pages() 在 higher-order 上返回 1,只会 zero 首页);在 post_alloc_hook 的 init 分支里,当 (gfp_flags & __GFP_ZERO) && user_addr != USER_ADDR_NONE 时改用 folio_zero_user()——它会把 fault 地址附近的 cache line 留到最后清,保证那些行在随即返回用户态时仍 hot。callsite 侧(vma_alloc_zeroed_movable_folioalloc_anon_foliovma_alloc_anon_folio_pmd、hugetlb fault / fallocate、memfd)改为直接传 __GFP_ZERO 并移除自己的 folio_zero_user(),顺手把 alpha / m68k / s390 / x86 上冗余的 arch override 删掉。

跟踪侧新增 PG_zeroed 复用 PG_private 位(从 PAGE_FLAGS_CHECK_AT_PREP 里排除),由 page_reporting_drain 在 host zero 后打上,由 __free_pages_ok / __free_frozen_pages 在 balloon deflate 走 FPI_ZEROED 打上;buddy merge 时"两者皆 zero 才保留"、split / expand 时向子 buddy 传播;post_alloc_hook 消费并清除。hugetlb 单独走 HPG_zeroed(存在 hugetlb folio ->private),在 alloc_surplus_hugetlb_folio 置位、free_huge_folio 清除,由 alloc_hugetlb_folio / alloc_hugetlb_folio_reserve 通过新增 bool *zeroed 输出给调用者。

收益

场景
指标
baseline
optimized
delta
2 GB VM / 1 vCPU / 256 MB anon+THP
task-clock
175 +- 10 ms
40 +- 9 ms
-77%
同上
cache-misses
924K +- 323K
287K +- 93K
-69%
同上
instructions
15.3M +- 634K
13.5M +- 337K
-12%
2 GB VM / 1 vCPU / 256 MB hugetlb surplus
task-clock
169 +- 9 ms
49 +- 19 ms
-71%
同上
cache-misses
1.24M +- 222K
316K +- 114K
-75%
同上
instructions
17.3M +- 1.23M
15.0M +- 604K
-13%

测试方法为作者提供的 alloc_once.c + bench.shmmap(..., MAP_PRIVATE|MAP_ANONYMOUS[|MAP_HUGETLB]) 后 madvise(MADV_POPULATE_WRITE) 再 munmap;每轮前 echo 512 > /sys/module/page_reporting/parameters/flush 触发 reporting,再以 perf stat 采样,n=10 取均值与 stddev。作者注明:优化在 THP 场景效果最佳,因为 2 MiB 页会整块地从 reported order-9 buddy 取出;无 THP 时由于低阶 fragmentation,只有约 21% 的 order-0 分配命中 reported 页。Persistent hugetlb pool 不受益,surplus hugetlb 则受益明显。RFC 仍在推进 virtio spec 侧变更,但作者显式请求 MM 部分(前 10 个 patch)先行独立 merge。


总结

新机制 / 新接口

#
系列
要点
6
Swap Table Phase IV
 [v3, 12p]
per-cluster swap_table 吞并 zeromap/swap_cgroup,删除 mm/swap_cgroup.c,anon/shmem swap-in 统一
7
Swap Tiers for cgroup
 [v6, 4p]
新增 /sys/kernel/mm/swap/tiers 与 memory.swap.tiers(.effective),按 cgroup 选择 swap 速度档
14
kmemleak verbose dedup
 [v1, 2p]
verbose scan 输出按 stackdepot trace_handle 去重
15
process_mrelease auto-kill + file folio evict
 [v1, 3p]
UAPI 新增 PROCESS_MRELEASE_REAP_KILL flag;reaper 上下文主动 mapping_evict_folio clean file folio
17
virtio skip redundant zeroing
 [RFC v3, 19p]
新 PG_zeroed/HPG_zeroed 标志把 host 已清零信息传递到 buddy 分配端,跳过冗余清零

性能优化

#
系列
量化数据
1
zsmalloc zs_free_deferred
 [RFC v2, 4p]
RK3588 unmap 256MB swap-filled VMA:63ms → 18.5ms(3.4x);12 CPU 并发 -20%
2
memory hotplug zone contiguous O(1)
 [v4, 2p]
virtio-mem 512G plug 36s → 7s(-81%)、unplug 36s → 9s(-75%)
4
kernel_init_pages batch clearing
 [v2, 1p]
16GB HugeTLB 分配 0.445s → 0.166s(2.68x);Graph500 64C128T sys -50.3%
13
SLUB __slab_try_return_freelist()
 [RFC, 1p]
省去 refill 归还的 cache-cold tail walk;新增 REFILL_RETURN_FAST/SLOW 计数器;无 benchmark

Bug Fix

#
系列
影响
12
huge zero folio MTE tag 初始化(重要)
 [v2, 1p]
Fixes: adfb6609c680;Cc: stable;init_on_free 下修复 MTE tag 信息泄漏,恢复文档承诺;selftest 17/18 通过
3
mmap_prepare 兼容路径 detached VMA 误 unmap
 [v1, 1p]
Fixes: ac0a3fc9c07d;Cc: stable;syzbot 报告;堆叠驱动下消除 vma_mark_detached WARN
5
anon_vma_name_reuse() NULL 返回处理
 [v1, 1p]
防御性修复:对 anon_vma_name_reuse() NULL 返回值做 NULL check,避免潜在解引用
16
hugetlb_cma per_node 日志取整
 [RFC, 1p]
修复日志打印的 per-node CMA 预留大小显示,作者自述 "No functional change to the actual reservation size"

内部优化 / 清理

#
系列
要点
10
alloc_tag 早期 PFN 动态链表
 [v2, 1p]
取代 8192 固定数组;复用 __GFP_NO_OBJ_EXT 作 __GFP_NO_CODETAG 打破递归
8
mm/gup pgtable entry accessors 统一
 [v2, 1p]
纯 cleanup:PMD/PUD 直接解引用改为访问器,无功能变化
9
mm/damon/sysfs filters/ 标记 deprecated
 [RFC, 3p]
纯文档:admin-guide 与 ABI 文档中标记 filters/ 目录为 deprecated
11
selftests/mm .gitignore 模式匹配
 [RFC, 1p]
纯维护:用通配符替代逐项忽略,向 KVM selftests 风格看齐

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-04 13:54:05 HTTP/2.0 GET : https://f.mffb.com.cn/a/488578.html
  2. 运行时间 : 0.175053s [ 吞吐率:5.71req/s ] 内存消耗:4,918.23kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=0fb7b057cf15e0d07721e2630c83cc33
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000383s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000580s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000231s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.002168s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000507s ]
  6. SELECT * FROM `set` [ RunTime:0.003118s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000586s ]
  8. SELECT * FROM `article` WHERE `id` = 488578 LIMIT 1 [ RunTime:0.011298s ]
  9. UPDATE `article` SET `lasttime` = 1783144445 WHERE `id` = 488578 [ RunTime:0.006308s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.002997s ]
  11. SELECT * FROM `article` WHERE `id` < 488578 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.003779s ]
  12. SELECT * FROM `article` WHERE `id` > 488578 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001798s ]
  13. SELECT * FROM `article` WHERE `id` < 488578 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.032824s ]
  14. SELECT * FROM `article` WHERE `id` < 488578 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.036511s ]
  15. SELECT * FROM `article` WHERE `id` < 488578 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.007187s ]
0.176721s