Linux memcg lru lock提升锁性能

news2024/9/18 11:11:55

内核关于per memcg lru lock的重要提交:

f9b1038ebccad354256cf84749cbc321b5347497

6168d0da2b479ce25a4647de194045de1bdd1f1d

计算虚拟地址转换基本机制

为了处理多应用程序的地址冲突, linux 系统在应用中使用了虚拟地址,得益于硬件的MMU的广泛使用,虚拟地址到实际内存的物理地址转化变得快速很多。

当虚拟地址送到cpu中后, 系统先前检查TLB表中是否有这个地址, 如果有,直接返回物理地址, 如果没有就去检查PageTable, 如果pagetable中也没有这个地址,系统产生一个page fault,来给这个地址实际分配物理内存。

每个应用的page table 保存了虚拟地址到物理地址一一对应表, 示意图如下所示:

Page fault 在linux中采用了称之为lazy fault的处理策略, 就是申请内存时并不实际分配物理内存, 直到实际使用这块内存时才实际分配内存。例如,得益于linux共享内存的设计,如果应用申请的share lib已经被其他程序实际分配到内存。 那么后来的应用只要在pagetable中填上对应的页表项就好。不需要发生实际的IO,这个过程叫做 minor fault. 第一个使用share lib的应用因为需要把share lib的内容读到内存, 需要有IO 的参与, 称之为Major fault.

问题背景

自电子计算机诞生以来,内存性能一直是行业关心的重点。内存也随着摩尔定律,在大小和速度上一直增长。现在的阿里云服务器动辄单机接近 TB 的内存大小,加上数以百记的 CPU 数量也着实考验操作系统的资源管理能力。

作为世间最流行的操作系统 Linux, 内核使用 LRU(Last Recent Used)链表来管理全部用户使用的内存,用一组链表串联起一个个的内存页,并且使用 lru lock 来保护链表的完整性。

所有应用程序常用操作都会涉及到 LRU 链表操作,例如,新分配一个页,需要挂在 inactive lru 链上, 2 次访问同一个文件地址, 会导致这个页从 inactive 链表升级到 active 链表, 如果内存紧张, 页需要从 active 链表降级到inactive 链表, 内存有压力时,页被回收导致被从 inactive lru 链表移除。不单大量的用户内存使用创建,回收关系到这个链表, 内核在内存大页拆分,页移动,memcg 移动,swapin/swapout, 都要把页移进移出 lru 链表。

可以简单计算一下 x86 服务器上的链表大小:x86 最常用的是 4k 内存页, 4GB 内存会分成 1M 个页, 如果按常用服务器 256GB 页来算, 会有超过 6 千万个页挂在内核 lru 链表中。超大超长的内存链表和频繁的 lru 操作造成了 2 个著名的内核内存锁竞争, zone lock 和 lru lock。这 2 个问题也多次在阿里内部造成麻烦,系统很忙,但是业务应用并没得到多少 cpu 时间, 大部分 cpu 都花在 sys 上了。一个简单 2 次读文件的 benchmark 可以显示这个问题, 它可以造成 70% 的 cpu 时间花费在 LRU lock 上。https://git.kernel.org/pub/scm/Linux/kernel/git/wfg/vm-scalability.git/tree/case-lru-file-readtwice

作为一个知名内核性能瓶颈, 社区也多次尝试以各种方法解决这个问题, 例如,使用更多的 LRU list, 或者 LRU contention 探测(https://lwn.net/Articles/753058/)。

但是都因为各种原因被 Linux 内核拒绝。

swap换入流程

cpu接到访问一个虚拟地址的命令, cpu需要把这个虚拟地址转化成物理地址,于是先去访问TLB,如果命中TLB,返回物理地址, 如果没有继续访问页表,如果命中页表, 返回物理地址, 如果没有命中, 产生page fault, 在page fault处理程序中,发现,虚拟地址对应的页表项虽然present bit 为零但是内容非空,所以这个地址在一个被交换到swap设备的页中。继续检查,这个页是否在swapcache中,如果在,返回这个页地址加虚拟地址地址在页中的偏移,如果不在,获得一个内存页, 到swap设备上读取内容填到这个页,此处产生IO, 为Major page fault. 接下了就上把这个页加到swapcache,加入 LRU, 加入page table, 关联到所属的memcg, 并且添加反向映射,然后用户就可以正常使用了。 最后在某些机器上在更新mmu cache.(spark/ppc)

linux kernel 使用LRU来管理内存页。 Last Recent Used.  内核页管理方式如下图所示:

lru 由2个链表组成,一个是inactive list, 另一个是active list, page fault新产生的页加到inactive list的头上, 二次访问到的页从inactive list上提升到active list上, 如果内存有压力回收时,active list的页降级的inactive list, inactive list页从尾巴上回收掉。

lru 页管理涉及到的内核数据有3个,per node 上的 Lru_lock, page.flags上的 PG_lru bit 和per node 5个链表。linux 把所有用户使用的内存页都放在5个链表上, inactive anon, active anon, inactivec file, active file and unevictable list.  

Lru_lock保护的对象有6个, 

加锁保护的时机如下:

在2008年以前, memcg加入内核之前, 内核使用一个per node lru_lock保护per node的lru lists.

当memcg引入内核后, lru list改成了 per memcg的模式,每个memcg都有一组lru lists.

当每个memcg的页共同还在同一个lru lock上竞争时, 显然不如给每个memcg一个lru lock, 这样lock contention就会大大减小。

使用per memcg 的 lru_lock, 要先解决一个问题: 内存页不会一直在一个memcg上固定不变, 页也许会被移动到其他的memcg上, 也许memcg会销毁。 所以使用per memcg lru lock的关键就是如何在在lru lock 锁定期间 保证memcg固定。
开始很直接想到的是relock方案:

page在memcg之间移动要获得lru_lock, 所以lru_lock relock可以保护page在memcg之间的移动, 但是回顾上面读取swap device的例子, 我们会在关联memcg之前加入lru list, 这个导致页所属的memcg不稳定, 因而会拿错Lru_Lock 。解决的根本是改变页加入lru list和memcg的次序:如下所示,先关联memcg, 然后在加入lru list.

关键步骤更新后,页管理中的锁的使用次序页可以改变了:

relock方案是可以用了。 但是relock 增加了lock 排队的机会 会导致性能下降。

更好的办法是不用lru_lock 保护memcg change, 比如拿出PG_lru bit做互斥: 原本的page isoaltion次序是: 

get_page; get lru_lock; clear page lru; delete page from lru list. 新的方法是,
get_page; TestClearPageLRU; get lru_lock; delete page from lru list. page isolation互斥从lru lock上移到PG_bit, 通过线性获得PG_lru bit来保证。lru lock只用来保证list的完整性。加上一些code clean up. 新的lru lock保护对象只保留了 lists.

另外lru_lock使用时机还是不变。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2141036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++题目】1.日期差值

日期差值 题目&#xff1a; 链接&#x1f517;&#xff1a;日期差值 代码&#xff1a; #include <iostream> using namespace std; /* *思路&#xff1a; * 1. 分别求出每一个日期与0000年0月1日距离的天数 * 2. 两个距离天数相减即可得到两个日期相差的天数 *///平年…

AIGC图片相关知识和实战经验(Flux.1,ComfyUI等等)

最近看了网上的一些新闻&#xff0c;flux.1火出圈了&#xff0c;因此自己也尝试跑了一下&#xff0c;作图的质量还是蛮高的&#xff0c;在这里做个知识总结回顾。 flux.1是什么&#xff1f; 根据介绍&#xff0c;flux.1是由stable diffusion 一作&#xff0c;Stability AI的核…

基于ssm的个性化影片推荐系统设计与实现

需要项目源码请联系我&#xff0c;目前有各类成品 毕设 javaweb ssh ssm springboot等等项目框架&#xff0c;源码丰富。 专业团队&#xff0c;咨询就送开题报告&#xff0c;活动限时免费&#xff0c;有需要的朋友可以来咨询。 一、摘要 随着科学技术的飞速发展&#xff0c;社…

matlab DFT的点数与周期

只需要0——N-1个点就可以算得另一个域全部的信号 周期 时域信号的全部长度时一个周期&#xff0c;所以时域的周期化没有混叠 频域的周期与采样率有关&#xff0c;会混叠。 取一个周期进行傅里叶变换都是对于周期化后的信号取得&#xff0c;由于时域周期化不混叠&#xff0c;所…

全方位解读信息架构:从挑战到解决方案,推动企业数字化转型的全面指南

在数字经济迅猛发展的今天&#xff0c;信息架构 已经成为企业实现数字化转型、提高运营效率和优化 IT 投资的关键手段。无论是初创企业还是成熟企业&#xff0c;构建和实施有效的信息架构不仅能支持业务增长&#xff0c;还能确保数据安全和合规性。《信息架构&#xff1a;商业智…

node.js 中的进程和线程工作原理

本文所有的代码均基于 node.js 14 LTS 版本分析 概念 进程是对正在运行中的程序的一个抽象&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;操作系统的其他所有内容都是围绕着进程展开的 线程是操作系统能够进行运算调度的最小单位&#xff0c;其是进程中的一个执…

Zookeeper学习

文章目录 学习第 1 章 Zookeeper 入门1.1 概述Zookeeper工作机制 1.2 特点1.3 数据结构1.4 应用场景统一命名服务统一配置管理统一集群管理服务器动态上下线软负载均衡 1.5 下载zookeeper 第 2 章 Zookeeper 本地安装2.1 本地模式安装安装前准备配置修改操作 Zookeeper本地安装…

【三方演化博弈】模型构建与模型求解

一、背景介绍二、收益矩阵计算2.1 博弈主体策略2.2 概率2.3 具体公式2.4 计算过程&#xff08;1&#xff09;企业&#xff08;2&#xff09;政府&#xff08;3&#xff09;环境NGO 三、期望与复制动态方程3.1 企业平均期望3.2 政府平均期望3.3 环境NGO平均期望3.4 三方演化博弈…

旋转链表问题(python3)

旋转链表 问题描述解题思路代码实现 问题描述 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 输入&#xff1a;head [1,2,3,4,5], k 2 输出&#xff1a;[4,5,1,2,3] 链表中节点的数目在范围 [0, 500] 内-100 < Node.va…

robomimic基础教程(一)——基本概念

robosuite和robomimic都是由ARISE Initiative开发的开源工具&#xff0c;旨在推进机器人学习和机器人操作领域的研究。 一、基本概念 robomimic是一个用于机器人示范学习的框架。它提供了在机器人操作领域收集的大量示范数据集&#xff0c;以及用于从这些数据集中学习的离线学…

828华为云征文|华为云Flexus云服务器X实例之openEuler系统下打造EnBizCard个人电子名片

828华为云征文&#xff5c;华为云Flexus云服务器X实例之openEuler系统下打造EnBizCard个人电子名片 一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 一、EnBizCard介绍2.1 EnBizCard简介2.2 EnBizCard特点…

CSS调整背景

一、设置背景颜色 通过 background-color 属性指定&#xff0c;值可以是十六进制 #ffffff&#xff0c;也可以是rgb(0, 255, 255)&#xff0c;或是颜色名称 "red" div {background-color: red; /* 通过颜色名称设置 */background-color: #ff0000; /* 通过十六进制设…

数据结构和算法之线性结构

原文出处:数据结构和算法之线性结构 关注码农爱刷题&#xff0c;看更多技术文章&#xff01;&#xff01;&#xff01; 线性结构是一种逻辑结构&#xff0c;是我们编程开发工作应用最广泛的数据结构之一。线性结构是包含n个相同性质数据元素的有限序列。它的基本特征是&…

求和(2)

题目描述 输入两个正整数 l,r&#xff0c;编程计算 l(l1)(l2)...(r−1)r 的结果并输出。 输入格式 一行两个整数 l 和 r 输出格式 一个整数&#xff0c;根据题意计算后的结果 样例数据 样例输入#1 1 5样例输出#1 15样例输入#2 8 10样例输出#2 27数据范围 对于100%的…

刷题DAY38

原样输出 题目&#xff1a;给定一个数n&#xff0c;请原样输出 输入&#xff1a;输入只有一个数&#xff0c;可能为小数&#xff0c;也可能为整数&#xff0c;-1000000<n<1000000 输出&#xff1a;原样输出 输入&#xff1a;1.123 输出&#xff1a;1.123 import ja…

鸿蒙媒体开发系列01——资源分类访问

如果你也对鸿蒙开发感兴趣&#xff0c;加入“Harmony自习室”吧&#xff01;扫描下方名片&#xff0c;关注公众号&#xff0c;公众号更新更快&#xff0c;同时也有更多学习资料和技术讨论群。 1、概述 应用开发过程中&#xff0c;经常需要用到颜色、字体、间距、图片等资源&am…

代码随想录刷题day34丨 62.不同路径 ,63. 不同路径 II

代码随想录刷题day34丨 62.不同路径 &#xff0c;63. 不同路径 II 1.题目 1.1不同路径 题目链接&#xff1a;62. 不同路径 - 力扣&#xff08;LeetCode&#xff09; 视频讲解&#xff1a;动态规划中如何初始化很重要&#xff01;| LeetCode&#xff1a;62.不同路径_哔哩哔哩…

【Linux】-基本指令(上)

&#x1f511;&#x1f511;博客主页&#xff1a;阿客不是客 &#x1f353;&#x1f353;系列专栏&#xff1a;深入代码世界&#xff0c;了解掌握 Linux 欢迎来到泊舟小课堂 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 与Windows环境不同&#xff0c;我们…

ASCII字符和中文字符的显示

目录 前言 ASCII字符的点阵显示 获取点阵 描点 main 中文字符的点阵显示 指定编码格式 汉字区位码 汉字点阵显示实验 打开汉字库文件 编写显示汉字的函数 使用 lcd_put_chinese 函数 前言 板子为韦东山老师的imx6ull板&#xff0c;要在LCD上实现字符的显示&#xf…

idea集成和使用Git指南

前言 Git是一个分布式的版本控制工具&#xff0c;可以管理我们开发过程中的源代码文件&#xff0c;而idea是Java的集成开发环境&#xff0c;在idea中配置Git&#xff0c;可以提高我们的团队开发效率。因此在idea中集成Git并使用Git管理我们的源代码是必要的 第一步&#xff1a;…