dcavalca / rpms / qemu

Forked from rpms/qemu a year ago
Clone

Blame ksmtuned

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
Justin M. Forbes 563054
debug() {
Justin M. Forbes 563054
    if [ -n "$DEBUG" ]; then
Justin M. Forbes 563054
        s="`/bin/date`: $*"
Justin M. Forbes 563054
        [ -n "$LOGFILE" ] && echo "$s" >> "$LOGFILE" || echo "$s"
Justin M. Forbes 563054
    fi
Justin M. Forbes 563054
}
Justin M. Forbes 563054
Justin M. Forbes 563054
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`
Justin M. Forbes 563054
debug 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
Justin M. Forbes 563054
debug 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
Justin M. Forbes 563054
debug 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
af1488
    local pidlist
af1488
    pidlist=$(pgrep -d ' ' -- '^qemu(-kvm|:.{1,11})$')
af1488
    if [ -n "$pidlist" ]; then
af1488
        ps -p "$pidlist" -o rsz=
af1488
    fi | awk '{ sum += $1 }; END { print sum }'
Mark McLoughlin cd8d5c
}
Mark McLoughlin cd8d5c
Mark McLoughlin cd8d5c
free_memory () {
Justin M. Forbes afaf04
    awk '/^(MemFree|Buffers|Cached):/ {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`
Justin M. Forbes 563054
    debug committed $committed free $free
Mark McLoughlin cd8d5c
    if [ $[committed + thres] -lt $total -a $free -gt $thres ]; then
Mark McLoughlin cd8d5c
        KSMCTL stop
Justin M. Forbes 563054
        debug "$[committed + thres] < $total and free > $thres, stop ksm"
Mark McLoughlin cd8d5c
        return 1
Mark McLoughlin cd8d5c
    fi
Justin M. Forbes 563054
    debug "$[committed + thres] > $total, start ksm"
Mark McLoughlin cd8d5c
    if [ $free -lt $thres ]; then
Mark McLoughlin cd8d5c
        npages=`increase_npages $KSM_NPAGES_BOOST`
Justin M. Forbes 563054
        debug "$free < $thres, boost"
Mark McLoughlin cd8d5c
    else
Mark McLoughlin cd8d5c
        npages=`increase_npages $KSM_NPAGES_DECAY`
Justin M. Forbes 563054
        debug "$free > $thres, decay"
Mark McLoughlin cd8d5c
    fi
Mark McLoughlin cd8d5c
    KSMCTL start $npages $sleep
Justin M. Forbes 563054
    debug "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