当前位置: 首页 > java >正文

[Linux]学习笔记系列 --[mm][list_lru]

文章目录

  • list_lru
      • `list_lru` 概述
      • 原理
      • 使用场景
      • 优点
      • 缺点
      • 其他方案
      • 总结
  • include/linux/list_lru.h
    • list_lru_init
  • mm/list_lru.c
    • list_lru_add 将对象(item)添加到 LRU(最近最少使用)列表中
    • list_lru_add_obj 将对象(item)添加到 LRU(最近最少使用)列表中
    • list_lru_del 从 LRU(最近最少使用)列表中删除指定的对象(item)
    • list_lru_del_obj 从 LRU(最近最少使用)列表中删除指定的对象(item
    • init_one_lru 初始化一个 `list_lru_one` 结构
    • __list_lru_init 初始化一个 `list_lru` 结构

在这里插入图片描述

https://github.com/wdfk-prog/linux-study

list_lru

list_lru 概述

list_lru 是 Linux 内核中的一种通用 LRU(最近最少使用)管理机制,用于高效地管理内存中的对象列表。它通过维护一个链表和相关的计数器,提供了对对象的添加、删除、隔离和遍历等操作。list_lru 的设计目标是优化内存回收过程,尤其是在内存压力下,通过与 shrinker 机制结合,释放不必要的内存资源。


原理

list_lru 的核心原理是通过链表和计数器管理对象的生命周期,并与内存控制组(memcg)和 NUMA 节点结合,提供灵活的 LRU 管理功能。以下是其主要原理:

  1. 链表管理

    • 每个 list_lru 结构维护一个链表(list_head),用于存储 LRU 对象。
    • 对象通过 list_lru_add 添加到链表尾部,通过 list_lru_del 从链表中移除。
  2. 计数器

    • 每个链表都有一个计数器(nr_items),用于记录链表中对象的数量。
    • 计数器的更新通过原子操作实现,确保线程安全。
  3. NUMA 节点支持

    • list_lru 支持 NUMA 节点,每个节点都有独立的链表和计数器。
    • 通过 page_to_nid 获取对象所在的 NUMA 节点,确保 LRU 操作的本地性。
  4. 内存控制组(memcg)支持

    • 如果启用了 CONFIG_MEMCGlist_lru 可以与内存控制组结合,支持基于 memcg 的 LRU 管理。
    • 每个 memcg 都有独立的链表,允许更细粒度的内存回收。
  5. shrinker 结合

    • list_lrushrinker 机制结合,提供对象的回收功能。
    • 当内存压力较大时,shrinker 会调用 list_lru_walk 遍历链表并隔离对象。

使用场景

  1. 内存回收

    • 在内存压力下,通过 list_lrushrinker 机制回收不必要的对象,释放内存资源。
  2. 文件系统缓存管理

    • 文件系统使用 list_lru 管理 inodedentry 的缓存,优化文件系统性能。
  3. NUMA 优化

    • 在 NUMA 系统中,通过 list_lru 的节点支持,确保 LRU 操作的本地性,减少跨节点访问的开销。
  4. 内存控制组(memcg)管理

    • 在启用了 CONFIG_MEMCG 的系统中,list_lru 提供基于 memcg 的 LRU 管理,支持更细粒度的内存回收。

优点

  1. 通用性

    • list_lru 是一种通用的 LRU 管理机制,适用于多种场景(如文件系统、内存回收)。
  2. 高效性

    • 使用链表和原子计数器管理对象,支持高效的添加、删除和遍历操作。
  3. NUMA 和 memcg 支持

    • 支持 NUMA 节点和内存控制组,提供灵活的 LRU 管理功能。
  4. shrinker 结合

    • shrinker 机制结合,优化内存回收过程,减少内存压力。

缺点

  1. 复杂性

    • list_lru 的实现较为复杂,涉及 NUMA 节点、memcgshrinker,可能增加开发和调试的难度。
  2. 性能瓶颈

    • 在高并发场景下,链表操作可能成为性能瓶颈,尤其是链表较长时。
  3. 内存开销

    • 每个 NUMA 节点和 memcg 都需要维护独立的链表和计数器,可能增加内存开销。

其他方案

  1. 直接 LRU 链表

    • 使用简单的 LRU 链表管理对象,不支持 NUMA 和 memcg
    • 优点:实现简单,适用于小规模场景。
    • 缺点:缺乏灵活性,性能较低。
  2. 基于哈希的缓存管理

    • 使用哈希表管理对象,结合 LRU 算法实现缓存管理。
    • 优点:支持快速查找,适用于高性能场景。
    • 缺点:实现复杂,内存开销较大。
  3. 自定义回收机制

    • 根据具体需求实现自定义的回收机制,替代 list_lru
    • 优点:针对性强,适合特定场景。
    • 缺点:增加开发复杂性。

总结

list_lru 是 Linux 内核中的一种通用 LRU 管理机制,提供了高效、灵活的对象管理功能。它通过链表和计数器管理对象,并支持 NUMA 节点和内存控制组,适用于文件系统缓存管理和内存回收等场景。尽管 list_lru 的实现较为复杂,但其通用性和高效性使其成为内核中重要的内存管理工具。在特定场景下,可以考虑使用直接 LRU 链表、哈希缓存或自定义回收机制作为替代方案。

include/linux/list_lru.h

list_lru_init

#define list_lru_init(lru)				\__list_lru_init((lru), false, NULL)
#define list_lru_init_memcg(lru, shrinker)		\__list_lru_init((lru), true, shrinker)

mm/list_lru.c

list_lru_add 将对象(item)添加到 LRU(最近最少使用)列表中

/* 调用方必须确保 memcg 生存期。 */
bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid,struct mem_cgroup *memcg)
{struct list_lru_node *nlru = &lru->node[nid];struct list_lru_one *l;/* 锁定与内存控制组(memcg)关联的 LRU 列表 */l = lock_list_lru_of_memcg(lru, nid, memcg, false, false);/* 如果无法锁定(例如 memcg 生命周期已结束),函数返回 false,表示添加失败 */if (!l)return false;/* 如果对象为空,表示它可以安全地添加到 LRU 列表中 */if (list_empty(item)) {/* 将对象添加到 LRU 列表的尾部 */list_add_tail(item, &l->list);/* 如果添加了第一个元素,则设置 shrinker bit */if (!l->nr_items++)/* Shrinker 位用于标记 LRU 列表需要被回收器(Shrinker)处理 */set_shrinker_bit(memcg, nid, lru_shrinker_id(lru));unlock_list_lru(l, false);atomic_long_inc(&nlru->nr_items);return true;}unlock_list_lru(l, false);return false;
}

list_lru_add_obj 将对象(item)添加到 LRU(最近最少使用)列表中

  • lRU 是一种缓存管理机制,优先保留最近使用的对象并逐步移除较少使用的对象。该函数支持内存控制组(Memory Control Groups,memcg)的感知功能,以优化内存管理
bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
{bool ret;int nid = page_to_nid(virt_to_page(item));/* return false; */if (list_lru_memcg_aware(lru)) {rcu_read_lock();ret = list_lru_add(lru, item, nid, mem_cgroup_from_slab_obj(item));rcu_read_unlock();} else {ret = list_lru_add(lru, item, nid, NULL);}return ret;
}
EXPORT_SYMBOL_GPL(list_lru_add_obj);

list_lru_del 从 LRU(最近最少使用)列表中删除指定的对象(item)

/* 调用方必须确保 memcg 生存期。 */
bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid,struct mem_cgroup *memcg)
{struct list_lru_node *nlru = &lru->node[nid];struct list_lru_one *l;l = lock_list_lru_of_memcg(lru, nid, memcg, false, false);if (!l)return false;if (!list_empty(item)) {list_del_init(item);l->nr_items--;unlock_list_lru(l, false);atomic_long_dec(&nlru->nr_items);return true;}unlock_list_lru(l, false);return false;
}

list_lru_del_obj 从 LRU(最近最少使用)列表中删除指定的对象(item

bool list_lru_del_obj(struct list_lru *lru, struct list_head *item)
{bool ret;int nid = page_to_nid(virt_to_page(item));if (list_lru_memcg_aware(lru)) {rcu_read_lock();ret = list_lru_del(lru, item, nid, mem_cgroup_from_slab_obj(item));rcu_read_unlock();} else {ret = list_lru_del(lru, item, nid, NULL);}return ret;
}
EXPORT_SYMBOL_GPL(list_lru_del_obj);

init_one_lru 初始化一个 list_lru_one 结构

static void init_one_lru(struct list_lru *lru, struct list_lru_one *l)
{INIT_LIST_HEAD(&l->list);spin_lock_init(&l->lock);l->nr_items = 0;
#ifdef CONFIG_LOCKDEPif (lru->key)lockdep_set_class(&l->lock, lru->key);
#endif
}

__list_lru_init 初始化一个 list_lru 结构

int __list_lru_init(struct list_lru *lru, bool memcg_aware, struct shrinker *shrinker)
{int i;lru->node = kcalloc(nr_node_ids, sizeof(*lru->node), GFP_KERNEL);if (!lru->node)return -ENOMEM;for_each_node(i)init_one_lru(lru, &lru->node[i].lru);// memcg_init_list_lru(lru, memcg_aware);// list_lru_register(lru);return 0;
}
EXPORT_SYMBOL_GPL(__list_lru_init);
http://www.xdnf.cn/news/18101.html

相关文章:

  • Redis-缓存-穿透-布隆过滤器
  • 测试Windows10IoT系统是否可以正常运行KingSCSDA3.8软件
  • Transformer架构的数学本质:从注意力机制到大模型时代的技术内核
  • 蓝凌EKP产品:JSP 性能优化和 JSTL/EL要点检查列表
  • Excel 表格数据自动填充
  • C语言私人学习笔记分享
  • Canny边缘检测
  • pyecharts可视化图表组合组件_Grid:打造专业数据仪表盘
  • python pandas库 series如何使用
  • 电脑上搭建HTTP服务器在局域网内其它客户端无法访问的解决方案
  • 【Tech Arch】Hive技术解析:大数据仓库的SQL桥梁
  • 【从零开始学习Redis】项目实战-黑马点评D2
  • Conda 环境 在AI 私有化部署 有怎么用?
  • 迅速掌握Git通用指令
  • C++内存模型
  • 数据结构代码分享-1 顺序表
  • Redis面试精讲 Day 23:Redis与数据库数据一致性保障
  • Python 设计模式详解 —— 掌握软件设计的通用解决方案
  • 常用的SQL语句
  • ReactNode 类型
  • Java学习笔记:IDEA简单使用技巧
  • 使用vscode的task.json来自动执行make命令,而不直接使用终端
  • Eclipse Tomcat Configuration
  • 基于Python的旅游推荐系统 Python+Django+Vue.js
  • 【抽象类和接口】
  • Javascript面试题及详细答案150道之(106-120)
  • HAL-USART配置
  • 数据电台询价的询价要求
  • 计算机毕业设计java的小天鹅酒店月子会所管理小天鹅酒店母婴护理中心管理系统设计小天鹅酒店产后护理会所信息化管理平台
  • 利用pyxlsbwriter包实现写入xlsb和xlsx格式及读取效率的比较