Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1389460
  • 博文数量: 120
  • 博客积分: 182
  • 博客等级: 入伍新兵
  • 技术积分: 2278
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-19 16:31
文章分类

全部博文(120)

文章存档

2015年(12)

2014年(13)

2013年(40)

2012年(55)

分类: LINUX

2014-04-04 20:03:53

Linux内核中和内存相关的2个系统参数的设置:

想要通过修改linux内存管理相关的参数设置来观察其对内存数据库的读写性能的影响,首先要了解一些linux内存管理相关的重要参数,先了解两个,如下。


介绍一些前提基础:

在非一致性内存访问(NUMA)情况下,CPU访问不同位置的内存,代价是不一样的。在多CPU情况下,对每个CPU来说都有本地内存和远端内存之分,访问本地内存的代价要比访问远端内存的代价小。

内存节点(node):内存节点主要是依据CPU访问代价的不同而划分的。在多CPU环境下,本地内存和远端内存就是不同的节点。而且,就算在单CPU环境下,访问所有的内存的代价都是一样的,依然存在内存节点的概念,只是此时只有一个内存节点而已,内核中用struct pg_data_t来描述内存分区。

内存分区(zone)linux会对内存节点做进一步的划分,再将一个内存节点划分为不同的区。内核中以struct zone来描述内存分区。通常一个节点分为DMANormal, HighMem三个内存区。

DMA内存区:直接内存访问区,通常是物理内存起始的16MB主要被一些外设使用,使得外围设备和主内存之间直接传输它们的I/O数据,而不需要系统CPU的参与。

Normal内存区:从16MB-896MB内存区。

HighMem内存区:896MB以后的内存区。

对一个内存节点来说,优先从HighMem分配,再从Normal或者DMA分配。

页框linux采用的是页式内存管理,页是物理内存管理的基本单位,每个内存分区是由大量的页框组成的,内核中用struct page来描述一个页框。关于内存节点内存区(zone)以及page的关系如下图所示:

注:其中zone_mem_map是一个页框的数组,它记录了一个内存分区的所有页框的使用情况。



1.min_free_kbyte代表系统中必须保留的可用空闲内存的最小值。

在系统初始化时会根据内存大小计算一个默认值,计算规则是:

  min_free_kbytes = sqrt(lowmem_kbytes * 16) = 4 * sqrt(lowmem_kbytes)(注:lowmem_kbytes即可认为是系统内存大小)
计算出来的值有最小最大限制,最小为128K,最大为64M。
可以看出,min_free_kbytes随着内存的增大不是线性增长,comments里提到了原因“because network bandwidth does not increase linearly with machine size”。随着内存的增大,没有必要也线性的预留出过多的内存,能保证紧急时刻的使用量便足矣。
这个参数值主要用于计算影响内存回收的三个水平标记参数watrmark[min/low/high]:


(1)每个zone区中都存在一套这三个参数,其中从小到大的顺序依次是watermark[min],watermark[low],watermark[high].

(2)当系统中空闲内存低于watermark[low]时,开始启用内核守护线程kswapd进行内存页面回收(每个zone中都会有一个kswapd),直到该zone的空闲内存页数量达到watermark[high]之后才停止回收行为。如果上层申请内存的速度太快,导致空闲内存降至watermark[min]以下,内核就会进行direct reclaim(直接回收),也就是说直接在应用程序的上下文中进行页面回收,再用回收来的内存满足内存申请。所以,当有这样的情况发生时就会阻塞应用程序的执行,会带来一定的响应延迟,甚至可能会触发OOM(Out Of Memory,内存溢出)。因为watermark[min]下的内存空间是留给系统特殊使用的,所以不会给用户态程序用。

前面说道 min_free_kbyte主要是用于计算watermark[min/low/high]的。具体的计算方法就是:


  1. watermark[min]=min_free_pages(min_free_kbyte换算为page单位的数,每个zone都有一套watermark参数,实际计算结果是根据各个zone的大小所占的总的内存大小的比例来计算的)
  2. watermark[low]=watermark[min] * 5/4
  3. watermark[high]=watermark[min] * 3/2

所以中间的buffer量为 high - low = low - min = per_zone_min_free_pages * 1/4

因为min_free_kbytes = 4* sqrt(lowmem_kbytes),也可以看出中间的buffer量也是跟内存的增长速度成开方关系。

关于每个zone中的watermark[min/low/high]可以通过查看/proc/zoneinfo的内容获得

  1. helianthus@Lenovo:~$ cat /proc/zoneinfo
  2. Node 0, zone DMA
  3. pages free 3815
  4. min 196
  5. low 245
  6. high 294
  7. ……
  8. protection: (0, 869, 1943, 1943)
  9. ……

  10. Node 0, zone Normal
  11.   pages free 28271
  12.         min 11054
  13.         low 13817
  14.         high 16581
  15. ……

  16.          protection: (0, 0, 8598, 8598)
  17. ……

  18. Node 0, zone HighMem
  19.   pages free 4249
  20.         min 128
  21.         low 3545
  22.         high 6963
  23. ……
  24.         protection: (0, 0, 0, 0)
  25. ……

min_free_kbytes大小的影响

就像前面说的,min_free_kbyte设置的越大,watermark就会越高,同时三个水平标志之间的内存量页会相应的增加,这就会导致较早的启动kswapd线程进行页回收,而且回收上来的内存页会比较多(直到watermark[high]才会停止),这就使得系统会预留过多的空闲内存,而在一定程度上导致了应用程序可用内存量的减少。min_free_kbyte设置的过小,则会导致系统的预留内存过小。极端情况下设置min_free_kbytes接近内存大小时,留给应用程序的内存就会太少而可能会频繁地导致OOM的发生。
min_free_kbytes设的过小,则会导致系统预留内存过小。kswapd回收的过程中也会有少量的内存分配行为(会设上PF_MEMALLOC)标志,这个标志会允许kswapd使用预留内存;另外一种情况是被OOM选中杀死的进程在退出过程中,如果需要申请内存也可以使用预留部分。这两种情况下让他们使用预留内存可以避免系统进入deadlock状态。

2.lowmem_reserve_ratio

(1)这个参数的作用是在各个zone之间预留一些空间,以防止高端zone在没有内存的情况下过度使用低端zone的内存资源。一般一个node的机器有三个zone:DMANormal, HighMem.低端内存DMA很小,有自己的特殊作用,比如发生DMA时只能分配DMA zone的低端内存,所以,要遵循尽量能使用高端内存时不使用低端内存,同时防止高端内存分配不足的时候抢占稀有的低端内存。

(2)计算方法:                                                                                                                                                                               

  1. helianthus@Lenovo:~$ cat /proc/sys/vm/lowmem_reserve_ratio
  2. 256 32 32

内核利用/proc/zoneinfo中的protection数组计算每个zone的预留页数,计算出来也是数组形式,可以在上面第1个参数讲解中看到。在进行内存分配时,这些预留页数值和watermark相加,一起来决定现在的内存是否满足分配请求,或者空闲内存是否过少需要启动回收机制。比如内核文档/Documentation/sysctl/vm.txt中给出了这样一个例子:

如果一个normal区(index = 2)的页申请来试图分配DMA区的内存,且现在使用的判断标准是watermark[low]时,内核计算出page_free = 1355,而watermark + protection[2] = 3 + 2004 = 2007 > page_free,则认为空闲内存太少而不予以分配。如果分配请求本就来自DMA zone,则 protection[0] = 0会被使用,而满足分配申请。zone[i] 的 protection[j] 计算规则如下:

  1. (i < j):
  2.  zone[i]->protection[j]
  3.  = (total sums of present_pages from zone[i+1] to zone[j] on the node) / lowmem_reserve_ratio[i];
  4. (i = j):
  5.   (should not be protected. = 0;
  6. (i > j):
  7.   (not necessary, but looks 0)

当在normal区分配了大量内存的时候,可用的低端内存可能就不够了,一些系统操作可能会失败并提示“EAGAIN”等的错误信息。在上面的lowmem_reserve_ratio中显示normal区保留了32页,假如想在常规区保留64页,则改写lowmem_reserve_ratio参数的值来实现:

  1. root@Lenovo:/home/helianthus# sudo echo "256 64 32" > /proc/sys/vm/lowmem_reserve_ratio
  2. root@Lenovo:/home/helianthus# cat /proc/sys/vm/lowmem_reserve_ratio
  3. 256 64 32
而想要设置永久值,则需要编辑/etc/sysctl.conf文件,在其中添加下列语句:

 vm.lowmem_reserve_ratio = 256 64 32

然后执行下列命令使之生效:
  1. root@Lenovo:/home/helianthus# sysctl -p
  2. vm.lowmem_reserve_ratio = 256 64 32
  3. root@Lenovo:/home/helianthus# cat /proc/sys/vm/lowmem_reserve_ratio
  4. 256    64    32
关于更多的(虚拟)内存参数的说明和修改都在kernel的文档/Documentation/sysctl/vm.txt中,里面把很多和虚拟内存相关的参数讲的很清楚。


linux内存回收机制如何被触发

当某个进程针对页面发出请求时,系统内核会首先检查首选项NUMA(非一致内存访问)区是否有足够的空余内存,以及是否存在1%以上的可回收的页面。这个百分比可以调节,并由vm.min_unmaped_ratio sysctl来决定。可回收页面属于由文件支持的页面(即与页面缓存存在映射关系的文件所产生的页面)但目前并未被映射到任何进程中的那些页面。/proc/meminfo中,可以很清楚地看到,所谓"可回收页面(reclaimable pages"就是那些"活动(文件)+非活动(文件)-被映射"Active(file)+Inactive(file)-Mapped)的内容。

系统内核如何判断多少空闲内存才够用呢?

内存会使用区“水平标记(watermarks)”,通过/proc/sys/vm/min_free_kbytes中的值来判断。同时它们也会检查/proc/sys/vm/lowmem_reserve_ratio中的值:

  1. helianthus@Lenovo:User-kernel-com$ cat /proc/sys/vm/lowmem_reserve_ratio
  2. 256    32    32(DMA Normal HighMem)

特定主机内经过计算的值会保存在/proc/zoneinfo中,并带有如下面所示的“低//高”(low/min/high)标签:

  1. Node 0, zone DMA
  2. pages free 3781
  3. min 196
  4. low 245
  5. high 294
  6. scanned 0
  7. spanned 4080
  8. present 3949
  9. ……

内核会在区内存空闲页面的数量低于水平标志时执行页面回收,当空闲页面的数量高于“低”水平标记后,页面回收操作就会中止。(注意:这一计算过程针对的是各个独立区(zone):即使其他区仍然拥有足够的空闲内存,只要当前区被触发,回收机制就会执行)



参考:

13.5/Documentation/sysctl/vm.txt
http://kernel.taobao.org/index.php/Kernel_Documents/mm_sysctl(淘宝内核组)

阅读(22081) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~