和聂工一起在如何在硬件资源有限的情况下尽量多的运行虚拟机的泥潭中苦苦挣扎。
想利用numa 的优势,但又因为内存资源总是不够,使用strict 的策略可能会导致oom,只好允许进程跨numa node 使用内存。
当在一台启用了numa 的物理机上,通过libvirt 的xml 给虚拟机添加内存策略preferred 后,期待的是它会先使用preferred 的node 上的内存,只有这个node 上的内存不足时,才考虑使用其他node.
但实际部署下来,经常发现很多进程在两个node 上都有内存,但通过numastat -m 来看其实preferred 的node 上往往还有不少可释放的buffer/cache 等。
后来查询得知这个行为和zone_reclaim_mode 有关。当zone_reclaim_mode 为0 时,如果当前zone 的内存低于low 水线,会倾向于从其他zone 申请内存,而所有的zone 按照numa 访问代价排成一个list,按顺序依次检查这些zone 的free pages 和low 水线的关系,并尝试分配内存。
当zone_reclaim_mode 为1 时,会倾向于先对当前zone 进行内存回收,回收一部分buffer/cache 后如果满足需求则从当前zone 进行分配。
从代码上来看,通过alloc_pages_nodemask 分配内存时,会调用get_page_from_freelist 函数,而当该函数分配不出page 时,则进入alloc_pages_slowpath.
1 | // mm/page_alloc.c |
只观察get_page_from_freelist
1 | // mm/page_alloc.c |
因此看来使用preferred 的模式时,由于buffer/cache 的存在free pages 会变少,而free 在low 以下时如果zone_reclaim_mode 为0 就会从其他zone 分配内存,所以看起来是多数进程在每个node 上都有点内存。而当zone_reclaim_mode 为1 时,倾向于先回收本zone 的buffer/cache,这个过程会导致sar 中的pgscand 上涨。