|
Mark McLoughlin |
cd8d5c |
#!/bin/bash
|
|
Mark McLoughlin |
cd8d5c |
#
|
|
Mark McLoughlin |
cd8d5c |
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
|
|
Mark McLoughlin |
cd8d5c |
# Released under the GPL
|
|
Mark McLoughlin |
cd8d5c |
#
|
|
Mark McLoughlin |
cd8d5c |
# Author: Dan Kenigsberg <danken@redhat.com>
|
|
Mark McLoughlin |
cd8d5c |
#
|
|
Mark McLoughlin |
cd8d5c |
# ksmtuned - a simple script that controls whether (and with what vigor) ksm
|
|
Mark McLoughlin |
cd8d5c |
# should search for duplicated pages.
|
|
Mark McLoughlin |
cd8d5c |
#
|
|
Mark McLoughlin |
cd8d5c |
# starts ksm when memory commited to qemu processes exceeds a threshold, and
|
|
Mark McLoughlin |
cd8d5c |
# make ksm work harder and harder untill memory load falls below that
|
|
Mark McLoughlin |
cd8d5c |
# threshold.
|
|
Mark McLoughlin |
cd8d5c |
#
|
|
Mark McLoughlin |
39f14e |
# send SIGUSR1 to this process right after a new qemu process is started, or
|
|
Mark McLoughlin |
39f14e |
# following its death, to retune ksm accordingly
|
|
Mark McLoughlin |
39f14e |
#
|
|
Mark McLoughlin |
cd8d5c |
# needs testing and ironing. contact danken@redhat.com if something breaks.
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
if [ -f /etc/ksmtuned.conf ]; then
|
|
Mark McLoughlin |
cd8d5c |
. /etc/ksmtuned.conf
|
|
Mark McLoughlin |
cd8d5c |
fi
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
KSM_MONITOR_INTERVAL=${KSM_MONITOR_INTERVAL:-60}
|
|
Mark McLoughlin |
cd8d5c |
KSM_NPAGES_BOOST=${KSM_NPAGES_BOOST:-300}
|
|
Mark McLoughlin |
cd8d5c |
KSM_NPAGES_DECAY=${KSM_NPAGES_DECAY:--50}
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
KSM_NPAGES_MIN=${KSM_NPAGES_MIN:-64}
|
|
Mark McLoughlin |
cd8d5c |
KSM_NPAGES_MAX=${KSM_NPAGES_MAX:-1250}
|
|
Mark McLoughlin |
cd8d5c |
# millisecond sleep between ksm scans for 16Gb server. Smaller servers sleep
|
|
Mark McLoughlin |
cd8d5c |
# more, bigger sleep less.
|
|
Mark McLoughlin |
cd8d5c |
KSM_SLEEP_MSEC=${KSM_SLEEP_MSEC:-10}
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
KSM_THRES_COEF=${KSM_THRES_COEF:-20}
|
|
Mark McLoughlin |
cd8d5c |
KSM_THRES_CONST=${KSM_THRES_CONST:-2048}
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
total=`awk '/^MemTotal:/ {print $2}' /proc/meminfo`
|
|
Mark McLoughlin |
cd8d5c |
[ -n "$DEBUG" ] && echo total $total
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
npages=0
|
|
Mark McLoughlin |
cd8d5c |
sleep=$[KSM_SLEEP_MSEC * 16 * 1024 * 1024 / total]
|
|
Mark McLoughlin |
cd8d5c |
[ $sleep -le 10 ] && sleep=10
|
|
Mark McLoughlin |
cd8d5c |
[ -n "$DEBUG" ] && echo sleep $sleep
|
|
Mark McLoughlin |
cd8d5c |
thres=$[total * KSM_THRES_COEF / 100]
|
|
Mark McLoughlin |
cd8d5c |
if [ $KSM_THRES_CONST -gt $thres ]; then
|
|
Mark McLoughlin |
cd8d5c |
thres=$KSM_THRES_CONST
|
|
Mark McLoughlin |
cd8d5c |
fi
|
|
Mark McLoughlin |
cd8d5c |
[ -n "$DEBUG" ] && echo thres $thres
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
KSMCTL () {
|
|
Mark McLoughlin |
cd8d5c |
case x$1 in
|
|
Mark McLoughlin |
cd8d5c |
xstop)
|
|
Mark McLoughlin |
cd8d5c |
echo 0 > /sys/kernel/mm/ksm/run
|
|
Mark McLoughlin |
cd8d5c |
;;
|
|
Mark McLoughlin |
cd8d5c |
xstart)
|
|
Mark McLoughlin |
cd8d5c |
echo $2 > /sys/kernel/mm/ksm/pages_to_scan
|
|
Mark McLoughlin |
cd8d5c |
echo $3 > /sys/kernel/mm/ksm/sleep_millisecs
|
|
Mark McLoughlin |
cd8d5c |
echo 1 > /sys/kernel/mm/ksm/run
|
|
Mark McLoughlin |
cd8d5c |
;;
|
|
Mark McLoughlin |
cd8d5c |
esac
|
|
Mark McLoughlin |
cd8d5c |
}
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
committed_memory () {
|
|
Mark McLoughlin |
cd8d5c |
# calculate how much memory is committed to running qemu processes
|
|
Mark McLoughlin |
cd8d5c |
local progname
|
|
Mark McLoughlin |
cd8d5c |
progname=${1:-qemu}
|
|
Mark McLoughlin |
cd8d5c |
ps -o vsz `pgrep $progname` | awk '{ sum += $1 }; END { print sum }'
|
|
Mark McLoughlin |
cd8d5c |
}
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
free_memory () {
|
|
Mark McLoughlin |
cd8d5c |
awk '/^(MemFree|Buffers|MemCached):/ {free += $2}; END {print free}' \
|
|
Mark McLoughlin |
cd8d5c |
/proc/meminfo
|
|
Mark McLoughlin |
cd8d5c |
}
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
increase_npages() {
|
|
Mark McLoughlin |
cd8d5c |
local delta
|
|
Mark McLoughlin |
cd8d5c |
delta=${1:-0}
|
|
Mark McLoughlin |
cd8d5c |
npages=$[npages + delta]
|
|
Mark McLoughlin |
cd8d5c |
if [ $npages -lt $KSM_NPAGES_MIN ]; then
|
|
Mark McLoughlin |
cd8d5c |
npages=$KSM_NPAGES_MIN
|
|
Mark McLoughlin |
cd8d5c |
elif [ $npages -gt $KSM_NPAGES_MAX ]; then
|
|
Mark McLoughlin |
cd8d5c |
npages=$KSM_NPAGES_MAX
|
|
Mark McLoughlin |
cd8d5c |
fi
|
|
Mark McLoughlin |
cd8d5c |
echo $npages
|
|
Mark McLoughlin |
cd8d5c |
}
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
adjust () {
|
|
Mark McLoughlin |
cd8d5c |
local free committed
|
|
Mark McLoughlin |
cd8d5c |
free=`free_memory`
|
|
Mark McLoughlin |
cd8d5c |
committed=`committed_memory`
|
|
Mark McLoughlin |
cd8d5c |
[ -n "$DEBUG" ] && echo committed $committed free $free
|
|
Mark McLoughlin |
cd8d5c |
if [ $[committed + thres] -lt $total -a $free -gt $thres ]; then
|
|
Mark McLoughlin |
cd8d5c |
KSMCTL stop
|
|
Mark McLoughlin |
cd8d5c |
[ -n "$DEBUG" ] && echo "$[committed + thres] < $total and free > $thres, stop ksm"
|
|
Mark McLoughlin |
cd8d5c |
return 1
|
|
Mark McLoughlin |
cd8d5c |
fi
|
|
Mark McLoughlin |
cd8d5c |
[ -n "$DEBUG" ] && echo "$[committed + thres] > $total, start ksm"
|
|
Mark McLoughlin |
cd8d5c |
if [ $free -lt $thres ]; then
|
|
Mark McLoughlin |
cd8d5c |
npages=`increase_npages $KSM_NPAGES_BOOST`
|
|
Mark McLoughlin |
cd8d5c |
[ -n "$DEBUG" ] && echo "$free < $thres, boost"
|
|
Mark McLoughlin |
cd8d5c |
else
|
|
Mark McLoughlin |
cd8d5c |
npages=`increase_npages $KSM_NPAGES_DECAY`
|
|
Mark McLoughlin |
cd8d5c |
[ -n "$DEBUG" ] && echo "$free > $thres, decay"
|
|
Mark McLoughlin |
cd8d5c |
fi
|
|
Mark McLoughlin |
cd8d5c |
KSMCTL start $npages $sleep
|
|
Mark McLoughlin |
cd8d5c |
[ -n "$DEBUG" ] && echo "KSMCTL start $npages $sleep"
|
|
Mark McLoughlin |
cd8d5c |
return 0
|
|
Mark McLoughlin |
cd8d5c |
}
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
39f14e |
function nothing () {
|
|
Mark McLoughlin |
39f14e |
:
|
|
Mark McLoughlin |
39f14e |
}
|
|
Mark McLoughlin |
39f14e |
|
|
Mark McLoughlin |
cd8d5c |
loop () {
|
|
Mark McLoughlin |
39f14e |
trap nothing SIGUSR1
|
|
Mark McLoughlin |
cd8d5c |
while true
|
|
Mark McLoughlin |
cd8d5c |
do
|
|
Mark McLoughlin |
39f14e |
sleep $KSM_MONITOR_INTERVAL &
|
|
Mark McLoughlin |
39f14e |
wait $!
|
|
Mark McLoughlin |
cd8d5c |
adjust
|
|
Mark McLoughlin |
cd8d5c |
done
|
|
Mark McLoughlin |
cd8d5c |
}
|
|
Mark McLoughlin |
cd8d5c |
|
|
Mark McLoughlin |
cd8d5c |
PIDFILE=${PIDFILE-/var/run/ksmtune.pid}
|
|
Mark McLoughlin |
cd8d5c |
if touch "$PIDFILE"; then
|
|
Mark McLoughlin |
cd8d5c |
loop &
|
|
Mark McLoughlin |
cd8d5c |
echo $! > "$PIDFILE"
|
|
Mark McLoughlin |
cd8d5c |
fi
|