linuxsir首页 LinuxSir.Org | Linux、BSD、Solaris、Unix | 开源传万世,因有我参与欢迎您!
网站首页 | 设为首页 | 加入收藏
您所在的位置:主页 > Linux及计算机学科基础理论版 >

Linux内存管理机制简单分析

时间:2018-06-04  来源:未知  作者:admin666

本文对Linux内存管理机制做一个简单的分析,试图让你快速理解Linux一些内存管理的概念并有效的利用一些管理方法。

NUMA

Linux 2.6开始支持NUMA( Non-Uniform Memory Access )内存管理模式。在多个CPU的系统中,内存按CPU划分为不同的Node,每个CPU挂一个Node,其访问本地Node比访问其他CPU上的Node速度要快很多。
 通过numactl -H查看NUMA硬件信息,可以看到2个node的大小和对应的CPU核,以及CPU访问node的distances。如下所示CPU访问远端node的distances是本地node的2倍多。

[root@localhost ~]# numactl -H
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23
node 0 size: 15870 MB
node 0 free: 13780 MB
node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31
node 1 size: 16384 MB
node 1 free: 15542 MB
node distances:
node  支持女孩们支持女孩们 1
  支持女孩们0:  支持女孩们10  支持女孩们21
  支持女孩们1:  支持女孩们21  支持女孩们10

通过numastat查看NUMA的统计信息,包括内存分配的命中次数、未命中次数、本地分配次数和远端分配次数等。

[root@localhost ~]# numastat
  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们 node0  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们 node1
numa_hit  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们2351854045  支持女孩们  支持女孩们  支持女孩们3021228076
numa_miss  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们 22736854  支持女孩们  支持女孩们  支持女孩们  支持女孩们 2976885
numa_foreign  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们 2976885  支持女孩们  支持女孩们  支持女孩们  支持女孩们22736854
interleave_hit  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们 14144  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们 14100
local_node  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们2351844760  支持女孩们  支持女孩们  支持女孩们3021220020
other_node  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们22746139  支持女孩们  支持女孩们  支持女孩们  支持女孩们 2984941

Zone

Node下面划分为一个或多个Zone,为啥要有Zone,两个原因:1.DMA设备能够访问的内存范围有限(ISA设备只能访问16MB);2.x86-32bit系统地址空间有限(32位最多只能4GB),为了使用更大内存,需要使用HIGHMEM机制。

ZONE_DMA

地址段最低的一块内存区域,用于ISA(Industry Standard Architecture)设备DMA访问。在x86架构下,该Zone大小限制为16MB。

ZONE_DMA32

该Zone用于支持32-bits地址总线的DMA设备,只在64-bits系统里才有效。

ZONE_NORMAL

该Zone的内存被内核直接映射为线性地址并可以直接使用。在X86-32架构下,该Zone对应的地址范围为16MB~896MB。在X86-64架构下,DMA和DMA32之外的内存全部在NORMAL的Zone里管理。

ZONE_HIGHMEM

该Zone只在32位系统才有,通过建立临时页表的方式映射超过896MB的内存空间。即在需要访问的时候建立地址空间和内存的映射关系,在访问结束后拆掉映射关系释放地址空间,该地址空间可以用于其他HIGHMEM的内存映射。

通过/proc/zoneinfo可以查看Zone相关的信息。如下所示X86-64系统上两个Node,Node0上有DMA、DMA32和Normal三个Zone,Node1上只有一个Normal Zone。

[root@localhost ~]# cat /proc/zoneinfo |grep -E "zone| free|managed"
Node 0, zone  支持女孩们  支持女孩们  支持女孩们DMA
  支持女孩们pages free  支持女孩们  支持女孩们 3700
  支持女孩们  支持女孩们  支持女孩们  支持女孩们managed  支持女孩们3975
Node 0, zone  支持女孩们  支持女孩们DMA32
  支持女孩们pages free  支持女孩们  支持女孩们 291250
  支持女孩们  支持女孩们  支持女孩们  支持女孩们managed  支持女孩们326897
Node 0, zone  支持女孩们 Normal
  支持女孩们pages free  支持女孩们  支持女孩们 3232166
  支持女孩们  支持女孩们  支持女孩们  支持女孩们managed  支持女孩们3604347
Node 1, zone  支持女孩们 Normal
  支持女孩们pages free  支持女孩们  支持女孩们 3980110
  支持女孩们  支持女孩们  支持女孩们  支持女孩们managed  支持女孩们4128056

Page

Page是Linux底层内存管理的基本单位,大小为4KB。一个Page映射为一段连续的物理内存,内存的分配和释放都要以Page为单位进行。进程虚拟地址到物理地址的映射也是通过Page Table页表进行,页表的每一项记录一个Page的虚拟地址对应的物理地址。

TLB

内存访问时需要查找地址对应的Page结构,这个数据记录在页表里。所有对内存地址的访问都要先查询页表,因此页表的访问次数是频率最高的。为了提高对页表的访问速度,引入了TLB(Translation Lookaside Buffer)机制,将访问较多页表缓存在CPU的cache里。因此CPU的性能统计里很重要的一项就是L1/L2 cache的TLB miss统计项。在内存较大的系统里,如256GB内存全量的页表项有256GB/4KB=67108864条,每个条目占用16字节的话,需要1GB,显然是CPU cache无法全量缓存的。这时候如果访问的内存范围较广很容易出现TLB miss导致访问延时的增加。

Hugepages

为了降低TLB miss的概率,Linux引入了Hugepages机制,可以设定Page大小为2MB或者1GB。2MB的Hugepages机制下,同样256GB内存需要的页表项降低为256GB/2MB=131072,仅需要2MB。因此Hugepages的页表可以全量缓存在CPU cache中。
 通过sysctl -w vm.nr_hugepages=1024可以设置hugepages的个数为1024,总大小为4GB。需要注意是,设置huagepages会从系统申请连续2MB的内存块并进行保留(不能用于正常内存申请),如果系统运行一段时间导致内存碎片较多时,再申请hugepages会失败。
 如下所示为hugepages的设置和mount方法,mount之后应用程序需要在mount路径下通过mmap进行文件映射来使用这些hugepages。

sysctl -w vm.nr_hugepages=1024
mkdir -p /mnt/hugepages
mount -t hugetlbfs hugetlbfs /mnt/hugepages

Buddy System

Linux Buddy System是为了解决以Page为单位的内存分配导致外内存碎片问题:即系统缺少连续的Page页导致需要连续Page页的内存申请无法得到满足。原理很简单,将不同个数的连续Pages组合成Block进行分配,Block按2的幂次方个Pages划分为11个Block链表,分别对应1,2,4,8,16,32,64,128,256,512和1024个连续的Pages。调用Buddy System进行内存分配时,根据申请的大小找最合适的Block。
 如下所示为各个Zone上的Buddy System基本信息,后面11列为11个Block链表里可用的Block个数。

[root@localhost ~]# cat /proc/buddyinfo
Node 0, zone  支持女孩们  支持女孩们  支持女孩们DMA  支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们3
Node 0, zone  支持女孩们  支持女孩们DMA32  支持女孩们  支持女孩们102  支持女孩们  支持女孩们 79  支持女孩们  支持女孩们179  支持女孩们  支持女孩们229  支持女孩们  支持女孩们230  支持女孩们  支持女孩们166  支持女孩们  支持女孩们251  支持女孩们  支持女孩们168  支持女孩们  支持女孩们107  支持女孩们  支持女孩们 78  支持女孩们  支持女孩们169
Node 0, zone  支持女孩们 Normal  支持女孩们 1328  支持女孩们  支持女孩们900  支持女孩们 1985  支持女孩们 1920  支持女孩们 2261  支持女孩们 1388  支持女孩们  支持女孩们798  支持女孩们  支持女孩们972  支持女孩们  支持女孩们539  支持女孩们  支持女孩们324  支持女孩们 2578
Node 1, zone  支持女孩们 Normal  支持女孩们  支持女孩们466  支持女孩们 1476  支持女孩们 2133  支持女孩们 7715  支持女孩们 6026  支持女孩们 4737  支持女孩们 2883  支持女孩们 1532  支持女孩们  支持女孩们778  支持女孩们  支持女孩们490  支持女孩们 2760

Slab

Buddy System的内存都是大块申请,但是大多数应用需要的内存都很小,比如常见的几百个Bytes的数据结构,如果也申请一个Page,将会非常浪费。为了满足小而不规则的内存分配需求,Linux设计了Slab分配器。原理简单说就是为特定的数据结构建立memcache,从Buddy System里申请Pages,将每个Page按数据结构的大小划分为多个Objects,使用者从memcache里申请数据结构时分配一个Object。
 如下所示为Linux查看slab信息的方法:

[root@localhost ~]# cat /proc/slabinfo
slabinfo - version: 2.1
# name  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们<active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
fat_inode_cache  支持女孩们  支持女孩们  支持女孩们 90  支持女孩们  支持女孩们 90  支持女孩们  支持女孩们720  支持女孩们 45  支持女孩们  支持女孩们8 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们0
fat_cache  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们 40  支持女孩们102  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们0
kvm_vcpu  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们16576  支持女孩们  支持女孩们支持女孩们  支持女孩们8 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们0
kvm_mmu_page_header  支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们168  支持女孩们 48  支持女孩们  支持女孩们2 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们支持女孩们  支持女孩们  支持女孩们0
ext4_groupinfo_4k  支持女孩们 4440  支持女孩们 4440  支持女孩们  支持女孩们136  支持女孩们 30  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们148  支持女孩们  支持女孩们148  支持女孩们  支持女孩们  支持女孩们0
ext4_inode_cache  支持女孩们 63816  支持女孩们65100  支持女孩们 1032  支持女孩们 31  支持女孩们  支持女孩们8 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们 2100  支持女孩们 2100  支持女孩们  支持女孩们  支持女孩们0
ext4_xattr  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们1012  支持女孩们 1012  支持女孩们  支持女孩们 88  支持女孩们 46  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们 22  支持女孩们  支持女孩们 22  支持女孩们  支持女孩们  支持女孩们0
ext4_free_data  支持女孩们  支持女孩们 16896  支持女孩们17600  支持女孩们  支持女孩们 64  支持女孩们 64  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们275  支持女孩们  支持女孩们275  支持女孩们  支持女孩们  支持女孩们0

通常我们都是通过slabtop命令查看排序后的slab信息:

  支持女孩们OBJS ACTIVE  支持女孩们USE OBJ SIZE  支持女孩们SLABS OBJ/SLAB CACHE SIZE NAME  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们
352014 352014 100%  支持女孩们  支持女孩们0.10K  支持女孩们 9026  支持女孩们 39  支持女孩们  支持女孩们 36104K buffer_head
 93492  支持女孩们93435  支持女孩们99%  支持女孩们  支持女孩们0.19K  支持女孩们 2226  支持女孩们 42  支持女孩们  支持女孩们 17808K dentry
 65100  支持女孩们63816  支持女孩们98%  支持女孩们  支持女孩们1.01K  支持女孩们 2100  支持女孩们 31  支持女孩们  支持女孩们 67200K ext4_inode_cache
 48128  支持女孩们47638  支持女孩们98%  支持女孩们  支持女孩们0.06K  支持女孩们  支持女孩们752  支持女孩们 64  支持女孩们3008K kmalloc-64
 47090  支持女孩们43684  支持女孩们92%  支持女孩们  支持女孩们0.05K  支持女孩们  支持女孩们554  支持女孩们 85  支持女孩们2216K shared_policy_node
 44892  支持女孩们44892 100%  支持女孩们  支持女孩们0.11K  支持女孩们 1247  支持女孩们 36  支持女孩们4988K sysfs_dir_cache
 43624  支持女孩们43177  支持女孩们98%  支持女孩们  支持女孩们0.07K  支持女孩们  支持女孩们779  支持女孩们 56  支持女孩们3116K Acpi-ParseExt
 43146  支持女孩们42842  支持女孩们99%  支持女孩们  支持女孩们0.04K  支持女孩们  支持女孩们423  支持女孩们102  支持女孩们1692K ext4_extent_status

kmalloc

和glibc的malloc()一样,内核也提供kmalloc()用于分配任意大小的内存空间。同样,如果放任应用程序随意从Page里申请任意大小的内存也会导致Page内???内存碎片化。为了解决内部碎片问题,Linux使用Slab机制来实现kmalloc内存分配。原理和Buddy System类似,即创建2的幂次方的Slab池用于kmalloc根据大小适配最佳的Slab进行分配。
 如下所示为用于kmalloc分配的Slabs:

[root@localhost ~]# cat /proc/slabinfo
slabinfo - version: 2.1
# name  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们<active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
kmalloc-8192  支持女孩们  支持女孩们  支持女孩们  支持女孩们 196  支持女孩们  支持女孩们200  支持女孩们 8192  支持女孩们  支持女孩们支持女孩们  支持女孩们8 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们 50  支持女孩们  支持女孩们 50  支持女孩们  支持女孩们  支持女孩们0
kmalloc-4096  支持女孩们  支持女孩们  支持女孩们  支持女孩们1214  支持女孩们 1288  支持女孩们 4096  支持女孩们  支持女孩们支持女孩们  支持女孩们8 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们161  支持女孩们  支持女孩们161  支持女孩们  支持女孩们  支持女孩们0
kmalloc-2048  支持女孩们  支持女孩们  支持女孩们  支持女孩们2861  支持女孩们 2928  支持女孩们 2048  支持女孩们 16  支持女孩们  支持女孩们8 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们183  支持女孩们  支持女孩们183  支持女孩们  支持女孩们  支持女孩们0
kmalloc-1024  支持女孩们  支持女孩们  支持女孩们  支持女孩们7993  支持女孩们 8320  支持女孩们 1024  支持女孩们 32  支持女孩们  支持女孩们8 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们260  支持女孩们  支持女孩们260  支持女孩们  支持女孩们  支持女孩们0
kmalloc-512  支持女孩们  支持女孩们  支持女孩们  支持女孩们 6030  支持女孩们 6144  支持女孩们  支持女孩们512  支持女孩们 32  支持女孩们  支持女孩们4 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们192  支持女孩们  支持女孩们192  支持女孩们  支持女孩们  支持女孩们0
kmalloc-256  支持女孩们  支持女孩们  支持女孩们  支持女孩们 7813  支持女孩们 8576  支持女孩们  支持女孩们256  支持女孩们 32  支持女孩们  支持女孩们2 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们268  支持女孩们  支持女孩们268  支持女孩们  支持女孩们  支持女孩们0
kmalloc-192  支持女孩们  支持女孩们  支持女孩们  支持女孩们15542  支持女孩们15750  支持女孩们  支持女孩们192  支持女孩们 42  支持女孩们  支持女孩们2 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们375  支持女孩们  支持女孩们375  支持女孩们  支持女孩们  支持女孩们0
kmalloc-128  支持女孩们  支持女孩们  支持女孩们  支持女孩们16814  支持女孩们16896  支持女孩们  支持女孩们128  支持女孩们 32  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们528  支持女孩们  支持女孩们528  支持女孩们  支持女孩们  支持女孩们0
kmalloc-96  支持女孩们  支持女孩们  支持女孩们  支持女孩们 17507  支持女孩们17934  支持女孩们  支持女孩们 96  支持女孩们 42  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们427  支持女孩们  支持女孩们427  支持女孩们  支持女孩们  支持女孩们0
kmalloc-64  支持女孩们  支持女孩们  支持女孩们  支持女孩们 48590  支持女孩们48704  支持女孩们  支持女孩们 64  支持女孩们 64  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们761  支持女孩们  支持女孩们761  支持女孩们  支持女孩们  支持女孩们0
kmalloc-32  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们7296  支持女孩们 7296  支持女孩们  支持女孩们 32  支持女孩们128  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们 57  支持女孩们  支持女孩们 57  支持女孩们  支持女孩们  支持女孩们0
kmalloc-16  支持女孩们  支持女孩们  支持女孩们  支持女孩们 14336  支持女孩们14336  支持女孩们  支持女孩们 16  支持女孩们256  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们 56  支持女孩们  支持女孩们 56  支持女孩们  支持女孩们  支持女孩们0
kmalloc-8  支持女孩们  支持女孩们  支持女孩们  支持女孩们  支持女孩们21504  支持女孩们21504  支持女孩们  支持女孩们  支持女孩们支持女孩们512  支持女孩们  支持女孩们1 : tunables  支持女孩们  支持女孩们支持女孩们  支持女孩们支持女孩们  支持女孩们0 : slabdata  支持女孩们  支持女孩们 42  支持女孩们  支持女孩们 42  支持女孩们  支持女孩们  支持女孩们0

内核参数

Linux提供了一些内存管理相关的内核参数,在/proc/sys/vm目录下可以查看或者通过sysctl -a |grep vm查看:

[root@localhost vm]# sysctl -a |grep vm
vm.admin_reserve_kbytes = 8192
vm.block_dump = 0
vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 20
vm.dirty_writeback_centisecs = 500
vm.drop_caches = 1
vm.extfrag_threshold = 500
vm.hugepages_treat_as_movable = 0
vm.hugetlb_shm_group = 0
vm.laptop_mode = 0
vm.legacy_va_layout = 0
vm.lowmem_reserve_ratio = 256  支持女孩们 256 32
vm.max_map_count = 65530
vm.memory_failure_early_kill = 0
vm.memory_failure_recovery = 1
vm.min_free_kbytes = 1024000
vm.min_slab_ratio = 1
vm.min_unmapped_ratio = 1
vm.mmap_min_addr = 4096
vm.nr_hugepages = 0
vm.nr_hugepages_mempolicy = 0
vm.nr_overcommit_hugepages = 0
vm.nr_pdflush_threads = 0
vm.numa_zonelist_order = default
vm.oom_dump_tasks = 1
vm.oom_kill_allocating_task = 0
vm.overcommit_kbytes = 0
vm.overcommit_memory = 0
vm.overcommit_ratio = 50
vm.page-cluster = 3
vm.panic_on_oom = 0
vm.percpu_pagelist_fraction = 0
vm.stat_interval = 1
vm.swappiness = 60
vm.user_reserve_kbytes = 131072
vm.vfs_cache_pressure = 100
vm.zone_reclaim_mode = 0

vm.drop_caches

vm.drop_caches是最常用到的参数,因为Linux的Page cache(文件系统缓存)机制会导致大量的内存被用于文件系统缓存,包括数据缓存和元数据(dentry、inode)缓存。当内存不足时,我们通过该参数可以快速释放文件系统缓存:

To free pagecache:
  支持女孩们  支持女孩们echo 1 > /proc/sys/vm/drop_caches
To free reclaimable slab objects (includes dentries and inodes):
  支持女孩们  支持女孩们echo 2 > /proc/sys/vm/drop_caches
To free slab objects and pagecache:
  支持女孩们  支持女孩们echo 3 > /proc/sys/vm/drop_caches

vm.min_free_kbytes

vm.min_free_kbytes用于决定内存低于多少时启动内存回收机制(包括上面提到的文件系统缓存和下面会提到的可回收的Slab),该值默认值较小,在内存较多的系统设置为一个较大的值(如1GB)可以在内存还不会太少时自动触发内存回收。但也不能设置太大,导致频繁应用程序经常被OOM killed。

sysctl -w vm.min_free_kbytes=1024000

vm.min_slab_ratio

vm.min_slab_ratio用于决定Slab池里可回收的Slab空间在该Zone里的占比达到多少时进行回收,默认是5%。但经过笔者试验,当内存充足时根本不会触发Slab回收,也只有在内存水位线达到上面min_free_kbytes时才会触发Slab回收。该值最小可以设置为1%:

sysctl -w vm.min_slab_ratio=1

总结

以上简单描述了Linux内存管理机制和几个常用的内存管理内核参数。

参考资料

Understanding The Linux Kernel 3rd Edition
[Linux Physical Memory Description]](http://www.ilinuxkernel.com/files/Linux_Physical_Memory_Description.pdf)

友情链接