在uWSGI中使用Linux KSM

Kernel Samepage Merging 是Linux 内核 >= 2.6.32 的一个特性,允许进程共享具有相同内容的内存页。这是由一个内核守护进程周期性执行扫描,对比,以及在可能的情况下,对特定内存区域进行合并来完成的。KVM生而为增强,它可以被用于使用公共数据的进程 (例如,带有语言解释器和标准库的uWSGI进程)。

如果你幸运的话,使用KSM可能会成倍减少你的uWSGI实例的内存使用。特别是在大量的 Emperor 部署中:为每个vassal启用KSM可能会节省大量的内存。uWSGI中的KSM是 Asidev s.r.l. 的Giacomo Bagnoli的想法。非常感谢他。

启用KSM守护进程

要启用KSM守护进程 (ksmd),只需设置 /sys/kernel/mm/ksm/run 为1,如下所示:

echo 1 > /sys/kernel/mm/ksm/run

注解

记得在机器启动的时候做这个,因为KSM守护进程并不是默认运行的。

注解

KSM是一个可选功能,必须由进程明确要求,因此只是启用KSM将不会拯救你的机器上的一切东西。

在uWSGI中启用KSM支持

如果你已经在一个内核中编译了带KSM支持的uWSGI了,那么你将能够使用 ksm 选项。这个选项将会指示uWSGI在每个请求或者master周期后注册经常内存映射 (通过 madvise 系统调用)。如果自上一次扫描后,并没有页面映射发生改变,那么就不会使用昂贵的系统调用。

性能影响

检查进程映射要求在每次请求之后解析 /proc/self/maps 文件。在一些设置中,这将降低性能。你可以通过传递一个参数给 ksm 选项来调整uWSGI页面扫描的频率。

# Scan for process mappings every 10 requests (or 10 master cycles)
./uwsgi -s :3031 -M -p 8 -w myapp --ksm=10

检查KSM是否工作良好

/sys/kernel/mm/ksm/pages_shared/sys/kernel/mm/ksm/pages_sharing 文件包含了关于KSM效率的统计信息。值越高,你的uWSGI实例消耗的内存越少。

使用collectd的KSM统计

一个像这样的简单的Bash脚本可以用来密切关注KSM的效率:

#!/bin/bash

export LC_ALL=C

if [ -e /sys/kernel/mm/ksm/pages_sharing ]; then
    pages_sharing=`cat /sys/kernel/mm/ksm/pages_sharing`;
    page_size=`getconf PAGESIZE`;
    saved=$(echo "scale=0;$pages_sharing * $page_size"|bc);
    echo "PUTVAL <%= cn %>/ksm/gauge-saved interval=60 N:$saved"
fi

在你的 collectd 配置中,添加诸如以下的东西:

LoadPlugin exec
<Plugin exec>
   Exec "nobody" "/usr/local/bin/ksm_stats.sh"
</Plugin>