123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- #!/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 progname
- progname=${1:-qemu-kvm}
- ps -C "$progname" -o rsz | awk '{ sum += $1 }; END { print 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-/run/ksmtune.pid}
- if touch "$PIDFILE"; then
- loop &
- echo $! > "$PIDFILE"
- fi
|