• Ukieweb

    佳的博客

    曾梦想仗剑天涯,后来工作忙没去。

linux内核中 关于内存相关的参数 缓存 写磁盘 /proc/sys/vm

在 linux 内核中有许多参数可以有用户进行配置。可以通过 sysctl -a 命令来查看。本文主要讲一些与内存相关的参数,关于内存相关的参数可以通过命令 sysctl -a | grep "vm\." 进行查看,其中各个参数在【官方文档】中也有详细描述。

1. /proc/sys/vm/

优化内核对 cache 和 dirty cache 的处理,主要是在这这个目录下。对于这个目录,官网是这样介绍的

This file contains the documentation for the sysctl files in /proc/sys/vm and is valid for Linux kernel version 2.6.29.
The files in this directory can be used to tune the operation of the virtual memory (VM) subsystem of the Linux kernel and the writeout of dirty data to disk.

大概解释下就是如下:

  • 在 sysctl 文件中配置的以 vm 开头的配置,存在这里面。对于Linux内核版本2.6.29+都是有效的。

  • 此目录中的文件可用于调优 Linux 内核的虚拟内存(VM)子系统的操作和将 dirty data 写到磁盘。即缓存相关的参数。

2. 重要的修改项

写文件时,先写入内核的 cache 中,后台进程 pdflush 或 flush-n:m 负责异步将写操作 writeback 到磁盘。

注意:直接修改 echo 100 /proc/sys/vm/min_free_kbytes  里面文件重启会失效 。还需要在 sysctl.conf 中修改 vm.min_free_kbytes = 100 


centos7 弃用的参数


extra_free_kbytes

这个不是官网 kernel 自带的接口。centos7 已经弃用

extra_free_kbytes 是 CentOS-6(kernel-2.6.32 导出的一个接口 ),该接口并未合入内核主线,它是 redhat 自己合入的一个patch。   

在 CentOS-7(kernel-3.10) 上删除了该接口,转而使用dirty ratio来触发,因为直接回收耗时长的直接原因就是因为回收的时候会去回收dirty page,所以CentOS-7的这种做法更加合理一些

extra_free_kbytes在某种程度上也浪费了一些内存的使用。  


手动释放缓存


drop_caches

更改 drop_caches 的值将导致内核丢弃clean caches,以及 reclaimable (可回收的) slab对象 (如 dentries 和 inode )。他们占用的内存将变成 free

To free pagecache:
    sync && echo 1 > /proc/sys/vm/drop_caches
    
To free reclaimable slab objects (includes dentries and inodes):
    sync && echo 2 > /proc/sys/vm/drop_caches
    
To free slab objects and pagecache:
    sync && echo 3 > /proc/sys/vm/drop_caches

这是一种非破坏性操作,不会释放任何 dirty objects。为了增加通过此操作释放的对象数量,用户可以在写入 /proc/sys/vm/drop_caches 之前运行 sync 。这将最大程度地减少系统上 dirty objects 的数量,释放更多的缓存。

该文件不是控制各种内核高速缓存(inodes,dentries,pagecache 等)增长的唯一方法,当系统上其他应用需要内存时,内核会自动回收这些对象。

使用此文件可能会导致性能问题。由于它丢弃了cached objects,因此重新创建被丢弃的objects可能会花费大量的 I/O 和 CPU,尤其是当它们使用过多时。所以在生产环境中谨慎使用。


page cache 策略 以下几个参数设定影响 dirty page 写入 disk 和其他回收策略


dirty_expire_centisecs 

dirty_writeback_centisecs默认值500,即5s ;单位厘秒 1s=100。这个进程 每隔一段时间 就被唤醒执行一次。他会检查这些 dirty page 脏页面 的时间是不是超时了,超时的话就会被写到磁盘。

dirty_writeback_centisecs

dirty_expire_centisecs默认值3000,即30s;单位 厘秒。定义 dirty page 脏页面 的超时时间,这个只是写磁盘的一个标准。就算一个都没超时,但脏页面很多的话,也是会写磁盘的。这个下面会讲。

实验1:验证超时时间 dirty_writeback_centisecs

console 1

[root@tmp vm]# cat dirty_expire_centisecs 
3000

[root@tmp vm]# echo 500 > dirty_expire_centisecs 

[root@tmp vm]# dd if=/dev/zero of=/tmp/wtest.txt bs=1M count=10        
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00580514 s, 1.8 GB/s

[root@tmp vm]# echo 700 > dirty_expire_centisecs                   

[root@tmp vm]# dd if=/dev/zero of=/tmp/wtest2.txt bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00819349 s, 1.3 GB/s

[root@tmp vm]# 
[root@tmp vm]#

console 2

[root@tmp ~]# cat while_check.sh 
#!/bin/bash
while true
do
sleep 1
echo `date` `cat /proc/meminfo  |grep -i dirty`
done

[root@tmp ~]# sh while_check.sh 
Wed Jan 15 17:45:00 CST 2020 Dirty: 16 kB
Wed Jan 15 17:45:01 CST 2020 Dirty: 16 kB
Wed Jan 15 17:45:02 CST 2020 Dirty: 16 kB
Wed Jan 15 17:45:03 CST 2020 Dirty: 16 kB
Wed Jan 15 17:45:04 CST 2020 Dirty: 10256 kB
Wed Jan 15 17:45:05 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:06 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:07 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:08 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:22 CST 2020 Dirty: 0 kB
Wed Jan 15 17:45:23 CST 2020 Dirty: 0 kB
Wed Jan 15 17:45:24 CST 2020 Dirty: 0 kB
Wed Jan 15 17:45:25 CST 2020 Dirty: 0 kB
Wed Jan 15 17:45:26 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:27 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:28 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:29 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:30 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:31 CST 2020 Dirty: 10240 kB
Wed Jan 15 17:45:32 CST 2020 Dirty: 10260 kB
Wed Jan 15 17:45:33 CST 2020 Dirty: 10260 kB
Wed Jan 15 17:45:34 CST 2020 Dirty: 10260 kB
Wed Jan 15 17:45:35 CST 2020 Dirty: 10260 kB
Wed Jan 15 17:45:36 CST 2020 Dirty: 20 kB
Wed Jan 15 17:45:37 CST 2020 Dirty: 20 kB
Wed Jan 15 17:45:38 CST 2020 Dirty: 20 kB

假如:超时时间 n,检测频率为 m; dirty data 被写入磁盘的时间为 x ,

那么: n <=  x <= n+m

dirty_background_bytes 和 dirty_background_ratio

  • vm.dirty_background_bytes = 0

  • vm.dirty_background_ratio = 10

dirty_background_bytes 为 0 时,则 dirty_background_ratio  生效否则 dirty_background_bytes 生效。

  • dirty_background_bytes : 这里不提,我们设定为 0  ,只修改百分比,提高通用性。

  • dirty_background_ratio :当 dirty pages / available memory (free pages + reclaimable pages 即 可回收page ) 的百分比达到设定阈值,启动相关内核线程 ( pdflush/flush/kdmflush ) 开始将脏页写入磁盘。如果该值过大,同时又有进程大量写磁盘(未使用DIRECT_IO)时,会使 pagecache 占用对应比例的系统内存。

dirty_bytes dirty_ratio

  • vm.dirty_bytes = 0

  • vm.dirty_ratio = 20

 dirty_bytes 为 0 时,则 dirty_ratio  生效否则 dirty_bytes 生效。

  • dirty_bytes : 这里不提,我们设定为 0  ,只修改百分比,提高通用性。

  • dirty_ratio :   dirty pages / available memory (free pages + reclaimable pages 即 可回收page ) 的百分比达到设定阈值, 系统就会阻塞新的写请求,直到脏页被回写到磁盘。此值过低时,遇到写入突增时,会造成短时间内pagecache脏页快速上升,造成写请求耗时增加。但是此值也不能设置的太高,当该值太高时,会造成内核flush脏页时,超过内核限制的120s导致进程挂起或中断。

min_free_kbytes

  • vm.min_free_kbytes = 90112

一般不用调整这个参数。这个参数用来指定强制Linux VM保留的内存区域的最小值,单位是kb。VM会使用这个参数的值来计算系统中每个低端内存域的watermark[WMARK_MIN]值。每个低端内存域都会根据这个参数保留一定数量的空闲内存页。

避免内核,在紧急时刻/内部逻辑分配不出内存而导致死锁等问题。也不可调的过高,否则容易导致系统判定内存不足而出发OOM逻辑。

vfs_cache_pressure

  • vm.vfs_cache_pressure = 100

该文件表示内核回收用于 directory inode cache 内存的倾向

缺省值100 表示内核将根据 pagecache 和 swapcache ,把 directory 和 inode cache 保持在一个合理的百分比;降低该值低于100,将导致内核倾向于保留 directory 和 inode cache;增加该值超过 100,将导致内核倾向于回收 directory 和 inode cache。

当 vfs_cache_pressure = 0时,内核将永远不会由于内存压力而回收 dentries and inodes,这很容易导致内存不足引起 OOM。

在 vfs_cache_pressure = 1000 的情况下,它会寻找比可用对象多十倍的可释放对象


OOM


oom_dump_tasks

  • vm.oom_dump_tasks = 1

启动 OOM 信息打印

当 OOM-KILLER 启动时,将会将各进程的 pid, uid, tgid, vm size, rss, pgtables_bytes, swapents, oom_score_adj, 名称等信息打印到 dmesg 里,管理员事后可以在 dmesg 信息中查看,定位问题。

oom_kill_allocating_task

  • vm.oom_kill_allocating_task = 0

控制是否杀死触发OOM的进程。

设置为 0 时,OOM-KILLER会扫描进程列表,选择一个进程来杀死。通常都会选择消耗内存最多的进程,杀死这样的进程后可以释放大量的内存。

设置为非 0 时,OOM-KILLER,只会简单地将触发OOM的进程杀死,避免遍历进程列表,减少了决策开销。

为了避免特殊的进程被 OOM-KILLER 干掉,可以修改 echo -1000 > /proc/$pid/oom_score_adj,禁止 OOM-KILLER 杀掉该进程

参考文档

官方网站

/proc/sys/vm下的那些dirty*

Linux Kernel VM 参数



0
0
下一篇:k8s pod 停止流程 preStop 停止前处理 自定义 --grace-period 宽限期

0 条评论

老佳啊

85后,大专学历,中原人士,家里没矿。

由于年轻时长的比较帅气,导致在别人眼里,我一直不谈恋爱的原因是清高,实则是自己的小自卑。最大的人生目标就是找一个相知相爱相容的人,共度余生。

和人相处时如果能感受到真诚,会非常注重彼此的关系,对别人没有什么心机,即使有利益冲突,一般也会以和为贵,因为在这个世界上,物质的东西,从来不会吸引到我。

特别迷恋那些大山大水,如果现在还能隐居,可能早就去了。对那些宏伟的有底蕴的人文景观比较不感冒。

从事于IT行业,却一直对厨房念念不忘,由于身材魁梧,总觉得自己上辈子是个将军,可惜这辈子没当兵,也不会打架。