记一次Linux server偶发CPU飙升问题的跟进与解决( 二 )


那实际应该保留多少free内存以及何时触发回收free内存呢?这里就需要引入linux的内存水位(watermark)概念了 , 具体可参考这篇文章--Linux内核调整watermark_scale_factor以缓解direct reclaim 。简单来说就是linux设置了min/low/high三个内存水位 , 对应free内存在不同水位线的行为如下:

  • free > high , 内存充足 , 什么都不用做
  • free内存由>high下降至<low , 唤醒kswapd开始内存回收--其他进程依然可以正常申请内存
  • 若free内存一直下降至<min, 分配新内存的进程会直接触发自己同步内存回收操作--direct claim
  • kswapd终于回收free内存至>high , 休眠100ms休眠100ms期间若free又下降至<low , 则再次唤醒kswapd , 并自增kswapd_low_wmark_hit_quickly值休眠100ms后若free变为<high , kswapd需继续回收内存至>high , 而后继续休眠100ms , 并自增kswapd_low_wmark_hit_quickly值休眠100ms后若free依然>high , kswapd将进入长期sleep等待下次被唤醒
内存水位计算与调整而watermark的min/low/high三者的取值具体是由两个内核参数min_free_kbytes和watermark_scale_factor决定的 , 简单来说--参考
vm内核参数之内存水位min_free_kbytes和保留内存lowmem_reserve_ratio
:
watermark[WMARK_MIN] = (min_free_kbytes/4) * zone.pages/zone.allpageswatermark[WMARK_LOW] = 5/4watermark[WMARK_MIN]watermark[WMARK_HIGH] = 3/2*watermark[WMARK_MIN]min水位直接由min_free_kbytes决定(后面的zone.pages/zone.allpages表示不同内存区按占总物理内存的比例均分对应水位值) , 而后min/low/high之间的差值则=1/4low , 所以在一台8G(7969M)的线上机器上min/low/high取值默认为:
Node 0, zoneDMAper-node statsnr_inactive_anon 21704nr_active_anon 171130nr_inactive_file 1490263nr_active_file 153139--Node 0, zoneDMA32pages free58451min6322low7902high9482node_scanned0--Node 0, zoneNormalpages free13169min10540low13175high15810node_scanned0主要的Normal区域的min/low/high差值也就10540


推荐阅读