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