深入研究打算机底层、Windows内核、Linux内核、Hotspot源码……聚焦做那些大家想学没地方学的课程。为了担保课程质量及传授教化效果,一年磨一剑,三年先后做了这些课程:手写JVM、手写OS、带你用纯汇编写OS、手写64位多核OS、实战Linux内核…
这篇文章给大家分享Linux内核内存模块一个很主要的知识点:水位线,便是这玩意
添加图片注释,不超过 140 字(可选)

这玩意干啥的呢?掌握内存回收的。这玩意是理解Linux内核物理内存管理模块一个非常主要的知识点,还有一个便是lowmem_reserve,这个后面写文章详谈
关于水位线,能搜到的资料还是蛮多的,有的讲得蛮好的,但是我没有看到一篇文章是单步调试Linux内核给出证明的,如所有讲底层的文章还是一样,只是讲事理。以是我准备取其精华去其糟粕,结合自己的理解,再结合我能做到的单步调试Linux内核,写一篇普通易懂、有理有据的文章。如果你以为有收成,用你的小手点下分享便是对我最大的支持,创作不易……
我会分享这些:
水位线是个什么东东,机制是若何的?Linux内核中有几条水位线,水位线的值是如何算出来的Linux内核是如何基于水位线掌握内存回收线程的NUMA架构中,水位线是如何事情的如果证明你说的都是对的我想根据业务需求调度内存,怎么做关注公众年夜众号【硬核子牙】,阅读更多我写的硬核文章,关于操作系统、Linux内核、Java虚拟机…
本文是基于64位Linux内核写的,以下,enjoy
01 水位线watermark
如果你是做Java、Python、PHP的,你肯定听过垃圾网络器(GC),你写程序时不用考虑内存的申请与回收,都是由虚拟机帮你完成的。那虚拟机如何知道何时回收呢?有个阈值对吧,内存利用达到那个阈值就启动回收线程进行回收。这里说的水位线就相称于是这个阈值
那Linux内核中有几条水位线呢?三条。对应的阈值便是三个:
添加图片注释,不超过 140 字(可选)
这三条水位线与内存回收线程之间是如何协同事情的呢?如图
添加图片注释,不超过 140 字(可选)
从图中我们可以得出:
如果内存容量在high水位线之上,线程kswapd进入sleep随着内存不断被利用,如果该zone中的可用内存,即managed_pages,低于low水位线,线程kswapd就会激活,进行异步内存回收如果该zone中的可用内存,低于min水位线,这时候就会进入同步内存回收,即在__alloc_pages_slowpath函数中壅塞分配内存并考试测验直接内存回收(reclaim)、内存压缩(compact)、愈甚者OOM Killer逼迫回收,直到tatol size大于high水位线,回收才会停滞虽然从图中能得出这些信息,但是我猜这些问题是你想问的。比如:
什么是zonekswapd与zone之间的关系水位线watermark与zone之间的关系接着走……
02 Linux内核内存构造有木有听过SMP、UMA、NUMA?不理解的话可以看下我之前写的干系文章 传送门
Linux内核是基于NUMA架构设计的,SMP/UMA架构被视为一个NUMA节点,如图
添加图片注释,不超过 140 字(可选)
每个NUMA节点,在Linux内核中对应一个pglist_data工具。将每个NUMA节点包含的内存划分为多个zone进行管理,在Linux内核中的存在形式便是zone工具,关于zone是如何划分的,上面提到的文章里有讲到
水位线是与zone干系联的,而回收线程是与pglist_data干系联的,即一个NUMA节点只有一个内存回收线程kswapd。其实在内存紧张的时候,除了内存回收,还有内存压缩,对应的线程是kcompactd,这个后面有机会再聊
添加图片注释,不超过 140 字(可选)
那水位线与zone之间的关系是若何的呢?如图
添加图片注释,不超过 140 字(可选)
到这里我们已经知道了:
Linux内核是基于NUMA架构进行设计的,SMP/UMA架构在Linux内核中被视为只有一个节点的NUMA架构,用pglist_data工具来表示,内置一个内存回收线程kswapdLinux内核将一个NUMA节点中的内存分成几个ZONE进行管理,如果是64位内核,则包含这三个ZONE:DMA、DMA32、NORMAL每个ZONE都有三条水位线:high、low、min,当每个zone的可用内存,即managed_pages,超越这三条水位线,分别会触发不同的内存回收机制接下来咱们就来单步调试Linux内核,看三条水位线的阈值是如何算出来的
03 单步调试Linux内核论证
high与low是在min的根本上算出来的,以是我们先来看min是怎么算出来的
网上的文章大部分都说到它们三个之间的关系是这样的,实在是错的
添加图片注释,不超过 140 字(可选)
我怎么证明他们说的是错的呢?我单步调试内核当作果的
添加图片注释,不超过 140 字(可选)
min的打算公式是这样的
min = 当前NUMA节点要保留的最少page数 当前zone的总page数 / 当前NUMA节点的总page数
你是不是想问:公式为什么是这样的?那你得去问写这个Linux内核源码的coder了
当前NUMA节点的总page数是怎么算出来的呢?是每个zone的managed_pages - high_pages相加得到的,如图
添加图片注释,不超过 140 字(可选)
得到当前NUMA节点的总page数=1259658pages
当前NUMA节点要保留的最少page数怎么算出来的呢?
添加图片注释,不超过 140 字(可选)
将打算得到的new_min_free_kbytes与用户想优化内存设置的user_min_free_kbytes进行比较,直接看代码吧
添加图片注释,不超过 140 字(可选)
经由一系列运算,得到当前NUMA节点要保留的最少page数=8978kbytes=2244pages
添加图片注释,不超过 140 字(可选)
打算min的三个数据都有了,就可以打算min的值了,比如DMA区域的min的值
2244 3977 / 1259658 = 7
添加图片注释,不超过 140 字(可选)
再来看high、low的值是如何算出来的
添加图片注释,不超过 140 字(可选)
mult_frac的运算公式是
添加图片注释,不超过 140 字(可选)
tmp便是在7乘以2与Result之间取最大值,结果是3。以是low的结果是10,high的结果是13
watermark_scale_factor的值是多少呢?
添加图片注释,不超过 140 字(可选)
我们学习一个东西是为了用对吧!
接下来看看,我们学会了水位线机制,那我们能用它来做什么呢?Linux内核内存调优!
接下来讲讲如何做内存调优
04 Linux内核内存优化
从上面的讲解中可以看出,Linux内核供应了两个参数让我们可以调度内存:
user_min_free_kbyteswatermark_scale_factor设置user_min_free_kbytes会影响三条水位线,设置watermark_scale_factor只会影响两条水位线:low、high。
user_min_free_kbytes更多地关注于担保系统在内存紧张时的稳定性和关键操作的可行性。以是内存密集型运用,可以调大user_min_free_kbytes,以减少同步回收内存的巨大花费
而watermark_scale_factor则供应了一种机制,根据系统当前的内存状况动态调度内存回收的敏感度,以平衡性能和资源利用。一样平常不太会调
如何设置这两个参数呢:
添加图片注释,不超过 140 字(可选)
这样设置会立即生效,对应的处理逻辑
添加图片注释,不超过 140 字(可选)
至此,关于水位线的all就讲完了。你学会(废)了吗?如果以为还不错,可以帮忙分享一下吗?