Merge "Change requested in launchpad bug #1288352" into 5.0
[packages/centos6/qemu.git] / ksmtuned
1 #!/bin/bash
2 #
3 # Copyright 2009 Red Hat, Inc. and/or its affiliates.
4 # Released under the GPL
5 #
6 # Author:      Dan Kenigsberg <danken@redhat.com>
7 #
8 # ksmtuned - a simple script that controls whether (and with what vigor) ksm
9 # should search for duplicated pages.
10 #
11 # starts ksm when memory commited to qemu processes exceeds a threshold, and
12 # make ksm work harder and harder untill memory load falls below that
13 # threshold.
14 #
15 # send SIGUSR1 to this process right after a new qemu process is started, or
16 # following its death, to retune ksm accordingly
17 #
18 # needs testing and ironing. contact danken@redhat.com if something breaks.
19
20 if [ -f /etc/ksmtuned.conf ]; then
21     . /etc/ksmtuned.conf
22 fi
23
24 debug() {
25     if [ -n "$DEBUG" ]; then
26         s="`/bin/date`: $*"
27         [ -n "$LOGFILE" ] && echo "$s" >> "$LOGFILE" || echo "$s"
28     fi
29 }
30
31
32 KSM_MONITOR_INTERVAL=${KSM_MONITOR_INTERVAL:-60}
33 KSM_NPAGES_BOOST=${KSM_NPAGES_BOOST:-300}
34 KSM_NPAGES_DECAY=${KSM_NPAGES_DECAY:--50}
35
36 KSM_NPAGES_MIN=${KSM_NPAGES_MIN:-64}
37 KSM_NPAGES_MAX=${KSM_NPAGES_MAX:-1250}
38 # millisecond sleep between ksm scans for 16Gb server. Smaller servers sleep
39 # more, bigger sleep less.
40 KSM_SLEEP_MSEC=${KSM_SLEEP_MSEC:-10}
41
42 KSM_THRES_COEF=${KSM_THRES_COEF:-20}
43 KSM_THRES_CONST=${KSM_THRES_CONST:-2048}
44
45 total=`awk '/^MemTotal:/ {print $2}' /proc/meminfo`
46 debug total $total
47
48 npages=0
49 sleep=$[KSM_SLEEP_MSEC * 16 * 1024 * 1024 / total]
50 [ $sleep -le 10 ] && sleep=10
51 debug sleep $sleep
52 thres=$[total * KSM_THRES_COEF / 100]
53 if [ $KSM_THRES_CONST -gt $thres ]; then
54     thres=$KSM_THRES_CONST
55 fi
56 debug thres $thres
57
58 KSMCTL () {
59     case x$1 in
60         xstop)
61             echo 0 > /sys/kernel/mm/ksm/run
62             ;;
63         xstart)
64             echo $2 > /sys/kernel/mm/ksm/pages_to_scan
65             echo $3 > /sys/kernel/mm/ksm/sleep_millisecs
66             echo 1 > /sys/kernel/mm/ksm/run
67             ;;
68     esac
69 }
70
71 committed_memory () {
72     # calculate how much memory is committed to running qemu processes
73     local progname
74     progname=${1:-qemu-kvm}
75     ps -C "$progname" -o rsz | awk '{ sum += $1 }; END { print sum }'
76 }
77
78 free_memory () {
79     awk '/^(MemFree|Buffers|Cached):/ {free += $2}; END {print free}' \
80                 /proc/meminfo
81 }
82
83 increase_npages() {
84     local delta
85     delta=${1:-0}
86     npages=$[npages + delta]
87     if [ $npages -lt $KSM_NPAGES_MIN ]; then
88         npages=$KSM_NPAGES_MIN
89     elif [ $npages -gt $KSM_NPAGES_MAX ]; then
90         npages=$KSM_NPAGES_MAX
91     fi
92     echo $npages
93 }
94
95
96 adjust () {
97     local free committed
98     free=`free_memory`
99     committed=`committed_memory`
100     debug committed $committed free $free
101     if [ $[committed + thres] -lt $total -a $free -gt $thres ]; then
102         KSMCTL stop
103         debug "$[committed + thres] < $total and free > $thres, stop ksm"
104         return 1
105     fi
106     debug "$[committed + thres] > $total, start ksm"
107     if [ $free -lt $thres ]; then
108         npages=`increase_npages $KSM_NPAGES_BOOST`
109         debug "$free < $thres, boost"
110     else
111         npages=`increase_npages $KSM_NPAGES_DECAY`
112         debug "$free > $thres, decay"
113     fi
114     KSMCTL start $npages $sleep
115     debug "KSMCTL start $npages $sleep"
116     return 0
117 }
118
119 function nothing () {
120     :
121 }
122
123 loop () {
124     trap nothing SIGUSR1
125     while true
126     do
127         sleep $KSM_MONITOR_INTERVAL &
128         wait $!
129         adjust
130     done
131 }
132
133 PIDFILE=${PIDFILE-/var/run/ksmtune.pid}
134 if touch "$PIDFILE"; then
135   loop &
136   echo $! > "$PIDFILE"
137 fi