操作系统-内存管理 - 2
2024-02-28 09:19:35 0 举报
AI智能生成
内存回收\申请大于物理内存的空间\Linux内核-task_struct
作者其他创作
大纲/内容
性能影响
场景
文件页回收
干净页直接释放内存,不会影响性能
脏页会先写回磁盘再释放内存,这个操作会发生磁盘I/O,会影响性能
匿名页回收
开启了swap机制,会将不常访问的匿名页换出到磁盘,下次访问再从磁盘读取到内存,会影响性能
回收倾向
文件页回收对系统性能影响比匿名页小
Linux 提供了一个 /proc/sys/vm/swappiness 选项,用来调整文件页和匿名页的回收倾向
swappiness 的范围是 0-100
数值越大,越积极使用 Swap,也就是更倾向于回收匿名页
数值越小,越消极使用 Swap,也就是更倾向于回收文件页
尽早触发kswapd内核线程异步回收内存
内存回收的指标
sar -B 1
分支主题
核心概念
pgscank/s
kswapd(后台回收线程) 每秒扫描的 page 个数
pgscand/s
应用程序在内存申请过程中每秒直接扫描的 page 个数
pgsteal/s
扫描的 page 中每秒被回收的个数(pgscank+pgscand)
系统抖动,观察到pgscand数值很大
直接内存回收导致
如何触发kswapd内核线程回收内存
剩余内存衡量标准
最小阈值(pages_min)
页低阈值(pages_low)
页高阈值(pages_high)
内存使用情况
分支主题
kswapd定期扫描内存使用情况,根据剩余内存进行内存回收工作
绿色部分,内存充足
蓝色部分,内存有一定压力,可以满足程序申请内存的请求
橙色部分,内存压力较大,所剩内存不多。kswapd0会执行内存回收,直到剩余内存大于pages_hign为止
红色部分,内存基本被耗尽,会触发直接内存回收,应用程序会被阻塞
NUMA 架构下的内存回收策略
分支主题
SMP架构
多个CPU处理器共享资源的电脑硬件架构,每个 CPU 访问内存所用时间都是相同
CPU 处理器核数的增多,多个 CPU 都通过一个总线访问内存,这样总线的带宽压力会越来越大,同时每个 CPU 可用带宽会减少,这也就是 SMP 架构的问题
NUMA架构
将每个CPU进行分组,每一组CPU用Node表示,一个Node可能包含多个CPU
每个Node有自己的独立资源,包括内存、I/O,每个Node可以通过互联模块总线进行通信
每个 Node 上的 CPU 都可以访问到整个系统中的所有内存
与内存回收关系
当某个Node内存不足时,系统可以从其他Node寻找空闲内存,也可以从本地内存中回收内存
模式
通过 /proc/sys/vm/zone_reclaim_mode 来控制
0 (默认值)
在回收本地内存之前,在其他 Node 寻找空闲内存
1
只回收本地内存
2
只回收本地内存,在本地回收内存时,可以将文件页中的脏页写回硬盘,以回收内存
4
只回收本地内存,在本地回收内存时,可以用 swap 方式回收内存
zone_reclaim_mode 一般建议设置为 0
系统出现还有一半内存的时候,却发现系统频繁触发「直接内存回收」,导致了影响了系统性能,那么大概率是因为 zone_reclaim_mode 没有设置为 0
导致当本地内存不足的时候,只选择回收本地内存的方式,而不去使用其他 Node 的空闲内存
访问远端 Node 的内存比访问本地内存要耗时很多,但是相比内存回收的危害而言,访问远端 Node 的内存带来的性能影响还是比较小的
如何保护一个进程不被OOM杀掉
OOM回收内存
在系统空闲内存不足的情况,进程申请了一个很大的内存,如果直接内存回收都无法回收出足够大的空闲内存,那么就会触发 OOM 机制,内核就会根据算法选择一个进程杀掉
标准
Linux 内核里有一个 oom_badness() 函数,它会把系统中可以被杀掉的进程扫描一遍,并对每个进程打分,得分最高的进程就会被首先杀掉
进程得分影响
第一,进程已经使用的物理内存页面数
第二,每个进程的 OOM 校准值 oom_score_adj
可以通过 /proc/[pid]/oom_score_adj 来配置的。我们可以在设置 -1000 到 1000 之间的任意一个数值,调整进程被 OOM Kill 的几率
oom_badness得分计算
// points 代表打分的结果
// process_pages 代表进程已经使用的物理内存页面数
// oom_score_adj 代表 OOM 校准值
// totalpages 代表系统总的可用页面数
points = process_pages + oom_score_adj*totalpages/1000
用「系统总的可用页面数」乘以 「OOM 校准值 oom_score_adj」再除以 1000,最后再加上进程已经使用的物理页面数,计算出来的值越大,那么这个进程被 OOM Kill 的几率也就越大
每个进程的 oom_score_adj 默认值都为 0,所以最终得分跟进程自身消耗的内存有关,消耗的内存越大越容易被杀掉。我们可以通过调整 oom_score_adj 的数值
如果你不想某个进程被首先杀掉,那你可以调整该进程的 oom_score_adj,从而改变这个进程的得分结果,降低该进程被 OOM 杀死的概率
如果你想某个进程无论如何都不能被杀掉,那你可以将 oom_score_adj 配置为 -1000
不建议将我们自己的业务程序的 oom_score_adj 设置为 -1000
因为业务程序一旦发生了内存泄漏,而它又不能被杀掉,这就会导致随着它的内存开销变大,OOM killer 不停地被唤醒,从而把其他进程一个个给杀掉
文件页
概念
内核缓存的磁盘数据(Buffer)和内核缓存的文件数据(Cache)都叫作文件页
如何回收
大部分文件页,都可以直接释放内存,以后有需要时,再从磁盘重新读取就可以了
被应用程序修改过,并且暂时还没写入磁盘的数据(也就是脏页),就得先写入磁盘,然后才能进行内存释放
回收干净页的方式是直接释放内存,回收脏页的方式是先写回磁盘后再释放内存
匿名页
概念
这部分内存没有实际载体,不像文件缓存有硬盘文件这样一个载体,比如堆、栈数据等
如何回收
这部分内存很可能还要再次被访问,所以不能直接释放内存
它们回收的方式是通过 Linux 的 Swap 机制,Swap 会把不常访问的内存先写到磁盘中,然后释放这些内存,给其他更需要的进程使用
再次访问这些内存时,重新从磁盘读入内存就可以了
回收算法
文件页和匿名页的回收都是基于 LRU 算法,也就是优先回收不常访问的内存
LRU 回收算法,实际上维护着 active 和 inactive 两个双向链表
active_list
活跃内存页链表,这里存放的是最近被访问过(活跃)的内存页
inactive_list
不活跃内存页链表,这里存放的是很少被访问(非活跃)的内存页
越接近链表尾部,就表示内存页越不常访问。这样,在回收内存时,系统就可以根据活跃程度,优先回收不活跃的内存
0 条评论
下一页