当前位置:首页>Linux>Linux MM 2026-05-25 最新 Feature 分析报告

Linux MM 2026-05-25 最新 Feature 分析报告

  • 2026-07-02 16:39:49
Linux MM 2026-05-25 最新 Feature 分析报告
目录
  1. MGLRU: 用 folio_mark_accessed 替代 folio_set_active 优化预读页面处理
  2. vmscan: 批量 TLB 刷新以减少脏页回收中的 IPI 开销
  3. page_owner per-fd filter:print_mode 与 NUMA 过滤
  4. SLUB: 批量分离 node partial slabs 减少锁内链表操作开销
  5. page_counter stock 重构:将 stock 从 mem_cgroup 下沉至 page_counter
  6. HMM 与 device page 迁移流程统一:在缺页处理中完成迁移
  7. SLUB sheave 分配本地 NUMA 节点优化
  8. zswap 按 cgroup 主动写回机制
  9. userfaultfd RWP:VM 客户机内存工作集追踪
  10. 通用 pagewalk API:pt_range_walk

1. MGLRU: 用 folio_mark_accessed 替代 folio_set_active 优化预读页面处理

系列[PATCH v2] mm/mglru: use folio_mark_accessed to replace folio_set_active作者: Barry Song版本: v2(1 个 patch)

背景

MGLRU(Multi-Gen LRU)对映射在页表中的 folio 给予较高优先级的回收保护。在 folio_add_lru() 中,当 MGLRU 启用且处于 page fault 路径时,会无条件调用 folio_set_active() 设置 PG_active 标志。预读(readahead)机制会一次性读入大量 folio,其中许多永远不会通过页表被访问,但 MGLRU 将它们全部标记为 active,放置在较高优先级的 generation 中。这些预读页面占据了"热门"位置,不断将真正的工作集页面挤出,导致错误回收和严重性能退化。

解决的问题

  • 预读页面污染工作集:readahead 引入的未被访问页面挤占了本应属于真正工作集的高优先级 generation 位置,导致连续 refault
  • anon 页面无条件保护lru_gen_folio_seq() 中对非文件页(anon、非 swapcache)无条件给予较低 generation 序号(即更高优先级),不区分是否确实被访问
  • working set refault 时的统计问题:在 lru_gen_refault() 中,无论 folio 是否确实属于 workingset,都会无条件累加 WORKINGSET_ACTIVATE 统计

如何做

核心思路是将"无条件 active"改为"按需标记、惰性激活"。涉及 4 个文件的 5 处关键修改:

  1. **folio_add_lru() (mm/swap.c)**:将无条件 folio_set_active(folio) 改为条件逻辑——workingset folio 保持 folio_set_active(),否则使用 folio_mark_accessed() 设置 referenced 标志。这意味着预读但未被访问的 folio 会进入较低优先级的 generation,仅当后续 folio_check_references() 检测到 PTE 确实有 referenced 标志时才会被提升。

  2. **lru_gen_folio_seq() (include/linux/mm_inline.h)**:删除对 anon folio 的无条件保护逻辑 (!folio_is_file_lru(folio) && !folio_test_swapcache(folio))。将 else 分支的 generation 计算改为 MAX_NR_GENS - (folio_test_workingset(folio) || folio_test_referenced(folio)),仅当 folio 被标记为 workingset 或 referenced 时才能获得更年轻的 generation。

  3. **lru_gen_set_refs() (mm/vmscan.c)**:在设置 PG_workingset 标志前增加 folio_test_active(folio) 的前提检查。只有已被激活的 folio(通过 page table walk 或 refault 被明确标识为应该保护的)才会被进一步标记为 workingset。

  4. **lru_gen_refault() (mm/workingset.c)**:将 folio_set_active() 和 WORKINGSET_ACTIVATE 统计移动到 if (workingset) 条件内。只有确实检测到该 folio 属于 workingset 时才设置 active 并计数。

  5. **folio_check_references() (mm/vmscan.c)**:对 workingset 判断逻辑进行相应调整,与 lru_gen_folio_seq() 中的改动保持一致。

收益

ARM64 平台 fio strided read 测试(4KB 对齐、64KB 间隔的跨步读取模式,memcg 400M 限制,600M 文件):

指标
改动前
改动后
File refaults
12,883,855
0
读带宽
58.5 MiB/s
5,078 MiB/s (86.8x)

x86 平台 fio strided read 测试(相同条件):

指标
改动前
改动后
File refaults
3,240,029
0
读带宽
13.2 MiB/s
7,708 MiB/s (584x)

x86 平台内核构建测试(20 线程 memcg 1GB 限制):

指标
改动前
改动后
active/inactive LRU 参考值
实际时间
1m50.764s
1m48.915s
1m49.928s
系统时间
4m0.012s
3m43.685s
 (-6.8%)
3m40.740s
pswpin
1,333,245
915,629
 (-31.3%)
463,452
pswpout
4,366,443
3,207,173
 (-26.5%)
2,309,119
refault_file
287,794
257,271
 (-10.6%)
562,555
refault_anon
1,347,963
931,259
 (-30.9%)
470,694

2. vmscan: 批量 TLB 刷新以减少脏页回收中的 IPI 开销

系列[PATCH v4 0/5] mm: batch TLB flushing for dirty folios in vmscan作者: Zhang Peng版本:v4(5 个 patch)

背景

在内存回收路径中,shrink_folio_list() 是核心函数,负责逐个处理待回收的 folio。当遇到脏 folio 需要进行 pageout(写入磁盘或 swap)时,内核需要在写入开始之前刷新 TLB,以清除可能存在的 writable PTE entry,防止 CPU 在 IO 开始后仍然执行写入操作。这一 TLB 刷新通过 try_to_unmap_flush_dirty() 实现,对于多核系统,TLB shootdown 需要跨所有核心发送 IPI(inter-processor interrupt),开销与 CPU 核数成正比。

当前实现的瓶颈在于:每个脏 folio 都会独立调用一次 try_to_unmap_flush_dirty(),意味着在有大量脏 folio 需要回收的场景下,会产生海量的 IPI,严重影响回收效率。

解决的问题

  • IPI 风暴问题:遍历回收列表时,每个脏 folio 触发一次 TLB shootdown,导致 IPI 数量和 CPU 核数成正比,在 16 核系统上基准测试产生了 5540 万次 TLB shootdown
  • 回收吞吐受限:IPI 开销占据了大量 CPU 时间,导致实际的回收吞吐量(bogo ops/s)受限

如何做

该系列前 4 个 patch 是重构准备,将 shrink_folio_list() 中的内联逻辑提取为独立函数:folio_activate_locked()(激活逻辑)、folio_free()(释放路径)、pageout_one()(pageout 状态机)、folio_try_unmap()(TTU 标志及 unmap 调用)。

Patch 5 实现了核心的批量优化。引入第二个 folio_batch(容量 31 个 folio)用于累积待刷新的脏 folio,以及新函数 pageout_batch()。核心流程为:

累积阶段(在 shrink_folio_list() 中):遇到脏 folio 时不再立即调用 try_to_unmap_flush_dirty(),而是 folio_unlock() 后将其加入 flush_folios 批次。解锁的注释说明:如果持续持有锁等待批次填满,会阻塞通过 swap cache 查找该 folio 的 swap fault。当批次满 31 个时调用 pageout_batch()

批量处理阶段pageout_batch() 函数):采用"复用原地数组"技巧——先用 folio_batch_reinit() 清空计数器(底层 folios 数组仍可访问),然后遍历保存的数量:对每个 folio 重新加锁(folio_trylock()),检查可驱逐条件(folio_test_writeback()folio_mapped()folio_maybe_dma_pinned()),对整个 batch 执行一次try_to_unmap_flush_dirty(),然后对 batch 中每个 folio 调用 pageout_one() 完成回写。

遍历结束后,若有剩余未满批次的 folio,在 shrink_folio_list() 末尾再调用一次 pageout_batch() 处理。

收益

测试环境:stress-ng --vm 16 --vm-bytes 2G --vm-keep --timeout 60s,16 CPU,约 32G 内存,8G swap,512M memcg 限制。

指标
改动前
改动后
变化
bogo ops/s
28,238.63
35,833.97
+26.9%
TLB shootdowns
55,428,953
17,621,697
-68.2%
Function call IPIs
34,073,695
14,498,768
-57.4%
pgscan_anon (pages)
52,856,224
60,252,894
+14.0%
pgsteal_anon (pages)
29,004,962
34,054,753
+17.4%

3. page_owner per-fd filter:print_mode 与 NUMA 过滤

系列[PATCH v9 0/4] mm/page_owner: add per-fd filter infrastructure for print_mode and NUMA filtering作者: Zhen Ni版本:v9(4 个 patch)

背景

page_owner 是内核内存分配追踪的核心调试工具,通过 page_ext 框架为每个物理页面记录分配调用栈、时间戳、PID/TGID 等信息。在大内存配置(250GB+)下收集 page_owner 信息会产生数 GB 的输出,带来三方面挑战:(1) 存储压力;(2) 从生产环境传输大文件的困难;(3) 用户态后处理工具的 CPU 开销。

文件体积膨胀的根本原因在于冗余的栈追踪信息:虽然内核已通过 stackdepot 对调用栈进行了去重(返回 32 位 handle),但 page_owner 在输出时为每个页面都展开并打印完整的调用栈文本。此外,在 NUMA 感知的生产部署中,OOM 事件通常是节点级别的,但此前 page_owner 无法按 NUMA 节点过滤。

解决的问题

  • 输出体积过大:250GB+ 内存系统中,page_owner 输出可达 10GB+
  • 性能瓶颈:输出完整调用栈的文本展开极为耗时
  • NUMA 过滤能力缺失:无法按 NUMA 节点选择性输出页面信息
  • 多用户并发读取冲突:之前的 debugfs 文件不支持独立过滤状态

如何做

整个方案围绕 per-file-descriptor 过滤状态 的设计展开,核心思路是为每次 open() 调用分配独立的过滤状态。

状态结构struct page_owner_filter_state)包含四个字段:print_mode(枚举值 PAGE_OWNER_PRINT_STACK / HANDLE / STACK_HANDLE)、nid_filternodemask_t 类型)、nid_filter_enabled(布尔标志)、lock(自旋锁,保护读写路径并发)。

文件操作改造:为 page_owner_fops 新增 .open.release.write 三个成员,权限从 0400 改为 0600.write 解析类似 shell 的命令字符串(如 mode=handle nid=0,2-3),使用 strsep() 分割,sysfs_match_string() 匹配 print_mode,nodelist_parse() 解析 NUMA 节点列表(支持单节点、范围、混合格式),最后在 spinlock 保护下原子提交。

print_mode 过滤handle 模式跳过调用栈展开,输出格式为 "handle: 1048577",文件体积缩减约 66%。handle 到实际调用栈的映射可通过现有 show_stacks_handles 接口离线查询。

NUMA 过滤:使用 memdesc_nid() 提取页面 node ID(特意替代 page_to_nid() 以绕过 PF_POISONED_CHECK 断言),与 nid_filter 做 node_isset() 检查。附带 tools/mm/page_owner_filter.c 用户态工具,提供完整的输入校验。

收益

测试环境:250GB+ 内存、4 节点 NUMA 的生产环境服务器,基于 v6.18-rc1 构建,启用 CONFIG_PAGE_OWNER

指标
完整栈模式(stack)
仅 handle 模式
改善
输出文件大小
244 MB
84 MB
缩减 ~66%
读取吞吐量
1x(基线)
~4.4x
约 4.4 倍加速
NUMA 过滤正确性
N/A
N/A
grep 验证 node= 字段 100% 准确

4. SLUB: 批量分离 node partial slabs 减少锁内链表操作开销

系列[PATCH] mm/slub: batch-detach node partial slabs作者: Hao Li版本:1 个 patch

背景

SLUB 分配器的 get_partial_node_bulk() 函数负责从 node 级别的 partial list 中获取一组 partial slab 到 per-CPU 的本地列表中。在持有 n->list_lock 自旋锁的情况下,原有实现对每个符合条件的 slab 执行 remove_partial(n, slab) + list_add() 操作——即单独从 node partial list 中删除、再单独添加到本地 pc->slabs 列表。

在实际运行中,该循环常常会连续分离出多个相邻的 slab,这意味着在锁临界区内反复操作链表指针(修改前后节点的 next/prev 指针),造成不必要的链表指针抖动和缓存行颠簸(cache line bouncing)。

解决的问题

  • 锁临界区内的重复链表操作:每个 slab 的 remove_partial() + list_add() 都涉及多次指针修改,当连续有多个匹配的 slab 时这些操作是冗余的
  • 链表指针抖动:反复修改链表节点指针,在多核并发争抢 n->list_lock 的场景下增加了缓存一致性协议开销

如何做

引入 first 和 last 两个 struct slab * 指针追踪连续匹配段。遍历 n->partial 列表时不再对每个 slab 执行 remove_partial() 和 list_add(),而是调用 slab_clear_node_partial(slab) 清除 partial 状态并递减 n->nr_partial 计数。当遇到 pfmemalloc_match() 不匹配的 slab 时(连续段中断),调用 list_bulk_move_tail(&pc->slabs, &first->slab_list, &last->slab_list) 一次性将整段移动到 pc->slabs 列表。

关键之处在于:list_bulk_move_tail() 仅修改该段首尾节点的指针及目标链表的相关指针,中间所有节点的指针无需逐个修改。这显著减少了锁临界区内的指针操作次数(从 2N 次降至常数级别)。

收益

测试用例
测试环境
性能数据
will-it-scale mmap2
will-it-scale 基准测试套件,mmap2 分配压力场景
性能提升约 5%

5. page_counter stock 重构:将 stock 从 mem_cgroup 下沉至 page_counter

系列[PATCH v3 0/7] mm/memcontrol, page_counter: move stock from mem_cgroup to page_counter作者: Joshua Hahn版本:v3(7 个 patch)

背景

memcg 当前在每个 CPU 上维护一个 "stock"(预充电缓存),缓存最多 MEMCG_CHARGE_BATCH(64)个已充电页面,使小分配可以避免每次充电都遍历昂贵的 mem_cgroup 层级并执行原子操作。这个机制在 try_charge_memcg() 的快速路径中被使用,是 memcg 性能的关键优化。

然而每个 CPU 的 memcg_stock_pcp 只能追踪最多 NR_MEMCG_STOCK(7)个 memcg。当单个 CPU 上活跃充电的 memcg 超过 7 个时,会随机选择一个受害者驱逐并排空其 stock,导致不必要的延迟和"颠簸"。此外,stock 管理与 struct mem_cgroup 紧密耦合,使得为 memcg 添加新的 page_counter 并拥有独立的 stock 变得极其困难——这正是作者的分层内存限制(tiered memory limits)系列所需的基础设施。

解决的问题

  • 7 槽位限制导致随机驱逐:超过 7 个活跃 memcg 时随机驱逐受害者,造成 stock 被频繁排空和重新填充,cache 命中率下降
  • stock 与 memcg 紧耦合:所有 page_counter 共享同一个 stock 资源,无法为新的 page_counter 单独启用 stock 加速路径
  • 充电路径逻辑复杂try_charge_memcg() 中的 stock 消费、贪婪充电、失败重试、refill 逻辑与 limit check 交织在一起

如何做

在 struct page_counter 中引入 per-CPU 的 struct page_counter_stock(包含 local_trylock_t lock 和 unsigned long nr_pages)。每个 page_counter 可以独立地通过 page_counter_enable/disable/free_stock() 管理自己的 stock。

充电路径简化page_counter_try_charge() 现在直接感知 stock——如果 stock 中有足够页面,直接从 stock 消费(无层级遍历);否则贪婪地请求 max(batch, nr_pages) 个页面,成功后将多余页面尝试存入 stock(使用 trylock,失败则 uncharge 回去)。try_charge_memcg() 中的 consume_stock()refill_stock()MEMCG_CHARGE_BATCH 批量重试逻辑全部被移除,简化为直接调用 page_counter_try_charge()

drain 路径重构drain_all_stock() 重构为以 CPU 为外循环遍历(而非以 memcg 为外循环),通过 work_on_cpu() 在每个 CPU 上调用 drain_stock_on_cpu(),复杂度从 O(memcgs * CPUs) 降至 O(CPUs)。cgroup v2 优化了跳过 root memcg 的路径。memcg 原有的 struct memcg_stock_pcp 被移除。

收益

40 CPU、50G 内存系统,反复 fault 和 madvise MADV_DONTNEED 释放匿名页测试(40 次试验各 50 次迭代):

场景
mm-new base
after
变化
1 cgroup
357 ms
358 ms
+0.28%
4 cgroups
1245 ms
1214 ms
-2.43%
32 cgroups
9281 ms
8970 ms
-3.47%

6. HMM 与 device page 迁移流程统一:在缺页处理中完成迁移

系列[PATCH v12 0/5] Migrate on fault for device pages作者: Mika Penttila版本:v12(5 个 patch)

背景

GPU 等设备驱动使用 HMM(Heterogeneous Memory Management)框架实现 CPU 与设备内存之间的页面迁移。现有流程将"缺页处理"(fault handling)和"页面迁移"(migration)作为两个独立的 page table walk 操作,由调用方自行编排顺序。

方案一(先 fault 再迁移):hmm_range_fault() fault in 页面,然后 migrate_vma_*() 迁移。即使大多数时候页面已 present 或为零页映射,仍需要 2 次 page table walk。方案二(先迁移再 fault):先 migrate_vma_*() 迁移,如检测到未 present 页则调用 hmm_range_fault() 再重新走迁移。最坏需要 3 次 page table walk。在 x86-64 平台上,单次 page table walk 的开销可超过 1000 个 CPU cycle。

解决的问题

  • 最坏情况下 3 次 page table walk 的严重性能损失
  • 常见路径(页面已 present)仍需要 2 次 walk 的低效设计
  • 调用方需要自行处理两种流程的编排和错误恢复,编码复杂且容易出错

如何做

核心思路是将迁移的"收集"(collect)阶段整合进 HMM 的 page table walk 中,使得一次 walk 同时完成 fault in 和 migration entry 的设置。

标志位与数据结构扩展:在 enum hmm_pfn_flags 中新增 HMM_PFN_REQ_MIGRATE 输入请求标志和 HMM_PFN_MIGRATEHMM_PFN_COMPOUND 输出标志。struct hmm_range 新增 struct migrate_vma *migrate 字段。enum migrate_vma_info 新增 MIGRATE_VMA_FAULT 标志。

HMM page walk 的锁管理重构struct hmm_vma_walk 扩展了 mmu_notifier_rangevmastart/end 以及锁管理字段。关键变化在于 hmm_vma_walk_pmd() 通过 pmd_lock() 持有 PMD 锁后进行迁移准备。新增 HMM_ASSERT_PTE_LOCKEDHMM_ASSERT_PMD_LOCKEDHMM_ASSERT_UNLOCKED 宏用于调试断言。

迁移准备逻辑移入 HMM walkhmm_vma_handle_migrate_prepare()(PTE 级别)和 hmm_vma_handle_migrate_prepare_pmd()(PMD 级别)实现迁移 entry 安装逻辑,包括处理 anonymous 零页、device private/coherent 页、拆分 large folio、安装 migration entry(通过 set_pte_at() 写入 swp entry,保留 dirty/accessed/soft-dirty/uffd-wp 属性位)。

migrate_vma_setup() 统一入口:原有的 migrate_vma_collect() 及相关 page walk ops 被删除(约 500 行)。migrate_vma_setup() 现在构造 struct hmm_range,设置 default_flags = HMM_PFN_REQ_MIGRATE,调用 hmm_range_fault() 完成收集。新增 migrate_hmm_range_setup() 接口将 HMM pfn 数组转换为 migrate pfn 数组。

收益

作者未提供独立的量化性能数据(cover letter 声明纯 migrate 路径吞吐与基线持平,"within error margin")。从代码逻辑推断的预期收益:

  • 将最坏情况下 3 次 page table walk 减少为 1 次,每次 walk 在 x86-64 上约 1000+ CPU cycles
  • 常见路径(页面已 present)从 2 次 walk 减少为 1 次
  • 从 migrate_device.c 删除约 500 行重复代码(8 files changed, 1053 insertions(+), 578 deletions(-)
  • migrate_vma.vma/start/end 在 fault 路径自动由 HMM pagewalker 填充,驱动代码更简洁
  • 统一的 MMU_NOTIFY_MIGRATE 通知范围由 walker 侧精确管理

7. SLUB sheave 分配本地 NUMA 节点优化

系列[PATCH] mm/slub: allocate sheaves on local memory nodes作者: Hao Li版本:v1(1 个 patch)

背景

Sheave(struct slab_sheaf)是 SLUB 分配器的 per-CPU 元数据结构,包含对象数组(objects[]),在本地快速路径中被频繁访问。当前使用 kzalloc() 分配 sheave,未指定 NUMA 节点提示,可能导致 sheave 被分配到远程 NUMA 节点。虽然功能正确,但从 NUMA 局部性角度并非最优。此外在启动阶段(bootstrap),需要为所有 possible CPU 分配 sheave,但此时只有 online CPU 的 cpu_to_mem() 已完成初始化,直接使用会出错。

解决的问题

  • kzalloc() 未指定 NUMA 节点,sheave 可能分配在远程节点上,per-CPU 快速路径面临跨 NUMA 节点内存访问
  • 启动阶段 cpu_to_mem() 仅为 online CPU 初始化,直接使用会出错

如何做

两个改动点(仅修改 mm/slub.c,+11/-4 行):

  1. 运行时分配__alloc_empty_sheaf() 新增 int node 参数,内部将 kzalloc() 替换为 kzalloc_node()alloc_empty_sheaf() 调用时传入 numa_mem_id()

  2. 启动阶段分配bootstrap_cache_sheaves() 中参考 __build_all_zonelists 的做法,使用 local_memory_node(cpu_to_node(cpu)) 计算内存节点号,而非调用尚未初始化的 cpu_to_mem()

收益

作者声明:"no measurable performance improvement was observed, but this approach is theoretically correct." 作者未提供性能数据。从代码逻辑推断的预期收益:

  • 在理论上减少跨 NUMA 节点访问延迟,sheaf 中所有对象均来自 local node,保证访问时不会触发远端内存读取
  • 对于 NUMA 亲和性敏感的 workload(如 per-node memory binding 场景),对象分配路径的 NUMA 一致性得到加强
  • 为未来在 NUMA 拓扑更复杂的系统(如 CXL memory 扩展)上的优化奠定正确性基础
  • 该路径处于非热路径(refill spilling 为低频事件),添加节点检查的额外开销极低

8. zswap 按 cgroup 主动写回机制

系列[PATCH v2 0/4] mm/zswap: Implement per-cgroup proactive writeback作者: Hao Jia版本:v2(4 个 patch)

背景

zswap 当前的写回(writeback)完全是反应式的:要么由 shrinker 在内存回收时触发,要么在 zswap pool 达到大小上限时触发。缺乏针对特定 cgroup 的主动写回手段。正如作者在 cover letter 中所述:"users may want to prepare for an upcoming memory-intensive workload by flushing cold memory to the backing storage when the system is relatively idle"。

解决的问题

  • 缺乏针对特定 cgroup 的主动 zswap 写回手段,shrinker 无法按用户意图精确控制写回目标
  • 系统处于稳态(无内存压力)时,zswap pool 中的冷页无法及时被刷出
  • 无法区分被动和主动写回:现有的 zswpwb 计数器混合了所有来源

如何做

整体方案从三个维度构建 per-cgroup 主动写回能力:

核心数据结构struct zswap_wb_iter 嵌入 struct mem_cgroup,作为 per-memcg 的回写游标,在指定 cgroup 子树的 zswap LRU 上持续推进写回。新增 zswpwb_proactive 计数器与被动 zswpwb 区分。

算法流程:用户通过 memory.reclaim 接口触发后,遍历目标 memcg 子树,对每个 memcg 调用 zswap_proactive_shrink_memcg() 遍历所有 N_NORMAL_MEMORY 节点上的 zswap LRU,通过 list_lru_walk_one() 配合 shrink_memcg_cb() 回调执行逐 entry 写回。扫描量由 ZSWAP_PROACTIVE_WB_SCAN_RATIO(16 倍剩余 budget)控制,批次大小为 ZSWAP_PROACTIVE_WB_BATCH(128 页)。双重限流保护防止扫描和写回对系统造成冲击。

用户接口:扩展已有 memory.reclaim 接口,新增 zswap_writeback_only token。当该 token 被指定时直接调用 zswap_proactive_writeback()。使用示例:echo "100M zswap_writeback_only" > memory.reclaim。该 key 与 swappiness 互斥,同时指定返回 -EINVAL

收益

作者未提供性能数据。从代码逻辑推断的预期收益:

  • 用户可在业务低峰期主动触发 cgroup zswap 写回,避免高峰期被动写回导致的性能抖动
  • Per-cgroup 粒度使定向内存管理成为可能,仅影响目标 cgroup 的压缩缓存
  • zswpwb_proactive 计数器实现主动/被动写回统计隔离,便于运维观测
  • 双重限流(扫描比例 16x + 批量上限 128 页)防止单次操作消耗过多 CPU
  • 复用已有 memory.reclaim 接口(基于 Yosry Ahmed 和 Nhat Pham 的 review 建议),避免引入新的 cgroup 控制文件

9. userfaultfd RWP:VM 客户机内存工作集追踪

系列[PATCH v4 00/14] userfaultfd: working set tracking for VM guest memory作者: Kiryl Shutsemau (Meta)版本:v4(14 个 patch)

背景

在现代虚拟化场景中,VMM(Virtual Machine Monitor)需要对客户机内存进行分层管理:将热页面保留在快速本地存储上,将冷页面驱逐到慢速分层或远端存储。这要求 VMM 能够 (1) 检测哪些页面正在被访问(工作集追踪),(2) 安全地驱逐冷页面,(3) 在页面被重新访问时按需取回。

现有的 userfaultfd 提供了 MODE_MISSING(缺页)、MODE_WP(写保护)、MODE_MINOR(minor fault),但没有一种模式能够高效地追踪读访问——MODE_WP 只拦截写操作,而 MODE_MISSING 需要实际解除页面映射,开销过大。

解决的问题

  • 缺少读访问追踪能力:MODE_WP 仅能捕获写操作,无法检测读访问
  • 现有方案开销大:使用 MODE_MISSING 需要将页面从页表中移除,每次检测周期都需要大量的 page fault 和重新映射
  • 缺少异步工作集扫描路径:同步模式下每次访问都需要与 userspace handler 通信,延迟高,不适合高频的周期性工作集检测

如何做

本系列新增 UFFDIO_REGISTER_MODE_RWP(Read-Write Protect)模式,与现有的 MISSING/WP/MINOR 并列。核心技术架构分为三层:

第一层:基础设施解耦(Patch 1-3)

引入 CONFIG_ARCH_HAS_PTE_PROTNONE,将 pte_protnone()/pmd_protnone() 从 CONFIG_NUMA_BALANCING 解耦(RWP 也需要使用 PROT_NONE PTE 作为访问追踪标记)。六种架构(x86_64、arm64、powerpc、s390、riscv、loongarch)选择该选项。uffd PTE 位重命名为 _PAGE_BIT_UFFD/pte_uffd(),同时承载 WP 和 RWP 两种语义,由 VMA 标志区分。

第二层:内核机制(Patch 4-7)

新增 VM_UFFD_RWP VMA 标志(与 VM_UFFD_WP 互斥)。MM_CP_UFFD_RWP change_protection 原语:安装 PAGE_NONE 并设置 uffd 位;MM_CP_UFFD_RWP_RESOLVE 恢复 vma->vm_page_prot 并清除 uffd 位。通过 change_pte_range()change_huge_pmd() 和 hugetlb_change_protection() 统一处理 anon、shmem、THP 和 hugetlb。在 swap、device-exclusive、migration、fork、mremap、mprotect 路径中保留 RWP 标记。khugepaged/rmap 中的 userfaultfd_wp() 检查扩展为 userfaultfd_protected()(覆盖 WP 和 RWP)。GUP 的 gup_can_follow_protnone() 对 VM_UFFD_RWP VMA 强制返回 false。

第三层:用户态接口(Patch 8-12)

新增 UFFDIO_RWPROTECT 保护/解除保护 ioctl。Fault 分发中 sync 模式通过 handle_userfault() 投递 UFFD_PAGEFAULT_FLAG_RWP 消息;async 模式内核原地解析——恢复原始 PTE 权限,清除 uffd 位,fault 线程不阻塞继续执行。UFFD_FEATURE_RWP_ASYNC 使能异步模式,UFFDIO_SET_MODE 运行时切换 sync/async。PAGEMAP_SCAN 集成新增 PAGE_IS_ACCESSED 标志,实现 O(1) 冷页发现。

典型 VMM 工作流:UFFDIO_RWPROTECT 安装保护 → sleep(interval) → PAGEMAP_SCAN(!PAGE_IS_ACCESSED) 发现冷页 → 切换 sync 模式 → 安全驱逐 → 恢复 async 模式。

收益

作者未提供性能数据。从代码逻辑推断的预期收益:

  • 利用 CPU 的 PROT_NONE 机制在硬件层面捕获所有访问(读和写),无需逐页改变页表即可实现工作集检测
  • 通过 PAGEMAP_SCAN 扫描 uffd 位(而非逐页触发 fault),检测周期内扫描开销与页面数量成正比但无需用户态-内核态来回切换
  • async 模式实现零消息开销的被动检测,sync 模式提供精确的 race-free 驱逐,可在运行时动态切换
  • anon、shmem、hugetlbfs 使用完全相同的 PROT_NONE + uffd 位机制,无需为不同内存类型编写不同逻辑
  • 51 个文件的修改广度表明该功能深入触及了 PTE 操作的各个关键路径,设计成熟度高

10. 通用 pagewalk API:pt_range_walk

系列[RFC PATCH v3 0/8] Implement a new generic pagewalk API作者: Oscar Salvador版本:RFC v3(8 个 patch)

背景

Linux 内核中存在多个需要遍历进程页表的子系统,如 /proc/pid/smapsnuma_mapspagemap 和 clear_refs。当前代码使用基于回调函数的通用 pagewalk API(struct mm_walk + mm_walk_ops),但其存在多个痛点:(1) 各 /proc 接口之间存在大量重复代码,(2) hugetlb 被特殊化为 PTE 级别处理,无法按真实的大页级别(PMD/PUD)来遍历,(3) 锁管理和批处理逻辑分散在各调用者中。

在 LSFMM/BPF 2025 上,社区达成共识:需要统一 pagewalk API 来取代现有回调式 API,使 HugeTLB 能够像普通页面一样被处理而无需特殊 case。

解决的问题

  • 代码重复fs/proc/task_mmu.c 中 smaps、numa_maps、pagemap、clear_refs 各自实现了大量相似的页表遍历逻辑
  • hugetlb 的特殊处理:当前 API 使用 .hugetlb_entry 回调伪装成 PTE 级别条目
  • 锁管理分散批处理不一致:每个调用者需要自行管理 PTL 锁和连续 PTE 批处理

如何做

实现全新的 pt_range_walk API,核心设计理念是"让 API 管理锁和批处理,调用者只需消费结果"。

基础设施:新增 softleaf_from_pud() 解析 1GB 大页,pmd_huge_lock()/pud_huge_lock() 统一 PMD/PUD 锁获取,folio_pmd_batch() 实现 PMD 级别的 folio 批处理(类比 folio_pte_batch())。

核心 API:定义 8 种内部返回类型(PT_TYPE_NONEFOLIOMARKERPFNSWAPMIGRATIONDEVICEHWPOISON)。API 包含 pt_range_walk_start()pt_range_walk_next()pt_range_walk_done() 三个函数。调用者通过 pt_type_flags_t 位掩码指定感兴趣的类型,API 自动跳过不感兴趣的类型。返回的 struct pt_range_walk 包含了 entry 的完整信息:folio、page、大小、可写/young/dirty 状态、页表级别、批处理条目数等。

接口转换:将 fs/proc/task_mmu.c 中 /proc/pid/smapsnuma_mapspagemapclear_refs 全部转换为使用新 API。hugetlb VMA 与普通 VMA 在同一循环中处理,无需 is_vm_hugetlb_page() 分支。

收益

作者未提供性能数据。从代码逻辑推断的预期收益:

  • 该文件代码从约 2295 行减少到约 1065 行(-1230 行,约 54%),消除了大量重复逻辑
  • hugetlb 不再需要 .hugetlb_entry 特殊回调,PUD/PMD 级别的 hugetlb 页按真实大小返回
  • 内置锁管理使调用者不再需要关心 PTL 获取/释放、VMA 遍历锁、pte_offset_map 配对等细节
  • 类型过滤使调用者通过位掩码精确控制感兴趣的类型,API 自动跳过不需要的条目
  • page-types 工具测试显示新旧 API 输出完全一致,pagemap_ioctl 测试 113/117 通过
  • 注意该系列仍为 RFC,作者明确指出还需解决 make_uffd_wp_huge_pte 的 PTE_MARKER 问题和 i_mmap_lock 获取问题

总结

性能优化

#
系列
量化数据
1
MGLRU: folio_mark_accessed
 [v2, 1p]
fio strided read: refault 从千万级降至 0,带宽提升 86-584x;内核构建 swap 相关指标 -26%~31%
2
vmscan: batch TLB flushing
 [v4, 5p]
TLB shootdowns -68.2%,IPI -57.4%,回收吞吐 +26.9%
3
page_owner per-fd filter
 [v9, 4p]
输出缩减 66%(244MB→84MB),读取性能提升 4.4x
4
SLUB: batch-detach partial slabs
 [1p]
will-it-scale mmap2 测试 +5%
5
page_counter stock 重构
 [v3, 7p]
32 cgroup 场景改善 3.5%,消除 7 槽位限制
6
HMM migrate on fault
 [v12, 5p]
将 2-3 次 page table walk 减少为 1 次,删除约 500 行重复代码
7
SLUB sheave local node
 [v1, 1p]
无实测性能提升,理论上 NUMA 局部性正确

新机制 / 新接口

#
系列
要点
8
zswap per-cgroup proactive writeback
 [v2, 4p]
通过 memory.reclaim 新增 zswap_writeback_only key,支持 cgroup 级主动 zswap 写回
9
userfaultfd RWP
 [v4, 14p]
新增 UFFDIO_REGISTER_MODE_RWP 模式,利用 PROT_NONE PTE 实现 VM 客户机内存工作集追踪,支持 sync/async 双模,51 个文件

内部优化 / 清理

#
系列
要点
10
pt_range_walk API
 [RFC v3, 8p]
新通用 pagewalk API,统一 hugetlb 处理,消除 /proc 接口中 ~54% 重复代码

Bug Fix

#
系列
影响
alloc_tag: fix use-after-free in /proc/allocinfo
模块卸载后 /proc/allocinfo 读取导致的 use-after-free,Fixes: 9f44df50fee4
mm: free HIGHATOMIC/CMA frozen pages via buddy
HIGHATOMIC/CMA 页面被重映射为 MIGRATE_MOVABLE,修复后直接通过 free_one_page() 释放
zram: writeback fixes
blk_idx 泄漏 + 压缩后页面尾部残留旧数据未清零
riscv: mm: mark_new_valid_map after hotplug vmemmap
RISC-V 缓存 non-present TLB 条目导致新映射不可见
mm/hugetlb_vmemmap: fix vmemmap restore rollback
tail-page 模板覆盖 head-page 元数据,Fixes: c0b495b91a47, Cc: stable
mm/damon: fix stale TLB young-state on arm64
ptep_test_and_clear_young() 不清除 TLB 导致 nr_accesses 始终为 0
mm/damon/ops-common: folio_test_lru after folio_get
投机性 lru 检查导致竞争中的 VM_BUG_ON_PGFLAGS,Fixes: 3f49584b262c, Cc: stable
mm: make mmap_miss accounting symmetric
VM_SEQ_READ 的 mmap_miss 计数不对称影响 readahead 行为

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 08:09:45 HTTP/2.0 GET : https://f.mffb.com.cn/a/495494.html
  2. 运行时间 : 0.209462s [ 吞吐率:4.77req/s ] 内存消耗:4,693.65kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=e6751c60626e69e4c2ecb5ad2ae5947e
  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.000755s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001023s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000515s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.026738s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001147s ]
  6. SELECT * FROM `set` [ RunTime:0.000459s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001114s ]
  8. SELECT * FROM `article` WHERE `id` = 495494 LIMIT 1 [ RunTime:0.015943s ]
  9. UPDATE `article` SET `lasttime` = 1783037385 WHERE `id` = 495494 [ RunTime:0.049867s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.007280s ]
  11. SELECT * FROM `article` WHERE `id` < 495494 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000910s ]
  12. SELECT * FROM `article` WHERE `id` > 495494 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000446s ]
  13. SELECT * FROM `article` WHERE `id` < 495494 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.006410s ]
  14. SELECT * FROM `article` WHERE `id` < 495494 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000773s ]
  15. SELECT * FROM `article` WHERE `id` < 495494 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.013796s ]
0.211068s