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