blob: 2f404c26fb0bdb58b8805b3e74e28389b1ad75bb [file] [log] [blame]
Ihar Hrachyshka2b4735f2017-02-10 06:17:37 +00001#!/bin/bash
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15set -o errexit
16
Clark Boylana40f9cb2018-04-04 14:02:30 -070017# TODO(frickler): make this use stackrc variables
18if [ -x /opt/stack/data/venv/bin/python ]; then
19 PYTHON=/opt/stack/data/venv/bin/python
20else
21 PYTHON=${PYTHON:-python3}
22fi
Ian Wienand9573edb2017-03-28 19:37:39 +110023
Ihar Hrachyshka2b4735f2017-02-10 06:17:37 +000024# time to sleep between checks
25SLEEP_TIME=20
26
27# MemAvailable is the best estimation and has built-in heuristics
28# around reclaimable memory. However, it is not available until 3.14
29# kernel (i.e. Ubuntu LTS Trusty misses it). In that case, we fall
30# back to free+buffers+cache as the available memory.
31USE_MEM_AVAILABLE=0
32if grep -q '^MemAvailable:' /proc/meminfo; then
33 USE_MEM_AVAILABLE=1
34fi
35
36function get_mem_unevictable {
37 awk '/^Unevictable:/ {print $2}' /proc/meminfo
38}
39
40function get_mem_available {
41 if [[ $USE_MEM_AVAILABLE -eq 1 ]]; then
42 awk '/^MemAvailable:/ {print $2}' /proc/meminfo
43 else
44 awk '/^MemFree:/ {free=$2}
45 /^Buffers:/ {buffers=$2}
46 /^Cached:/ {cached=$2}
47 END { print free+buffers+cached }' /proc/meminfo
48 fi
49}
50
51function tracker {
52 local low_point
53 local unevictable_point
54 low_point=$(get_mem_available)
55 # log mlocked memory at least on first iteration
56 unevictable_point=0
57 while [ 1 ]; do
58
59 local mem_available
60 mem_available=$(get_mem_available)
61
62 local unevictable
63 unevictable=$(get_mem_unevictable)
64
65 if [ $mem_available -lt $low_point -o $unevictable -ne $unevictable_point ]; then
66 echo "[[["
67 date
68
69 # whenever we see less memory available than last time, dump the
70 # snapshot of current usage; i.e. checking the latest entry in the file
71 # will give the peak-memory usage
72 if [[ $mem_available -lt $low_point ]]; then
73 low_point=$mem_available
74 echo "---"
75 # always available greppable output; given difference in
76 # meminfo output as described above...
77 echo "memory_tracker low_point: $mem_available"
78 echo "---"
79 cat /proc/meminfo
80 echo "---"
81 # would hierarchial view be more useful (-H)? output is
82 # not sorted by usage then, however, and the first
83 # question is "what's using up the memory"
84 #
85 # there are a lot of kernel threads, especially on a 8-cpu
86 # system. do a best-effort removal to improve
87 # signal/noise ratio of output.
88 ps --sort=-pmem -eo pid:10,pmem:6,rss:15,ppid:10,cputime:10,nlwp:8,wchan:25,args:100 |
89 grep -v ']$'
90 fi
91 echo "---"
92
93 # list processes that lock memory from swap
94 if [[ $unevictable -ne $unevictable_point ]]; then
95 unevictable_point=$unevictable
Vasyl Saienkodea30832017-08-01 00:16:51 +030096 ${PYTHON} $(dirname $0)/mlock_report.py
Ihar Hrachyshka2b4735f2017-02-10 06:17:37 +000097 fi
98
99 echo "]]]"
100 fi
101 sleep $SLEEP_TIME
102 done
103}
104
105function usage {
106 echo "Usage: $0 [-x] [-s N]" 1>&2
107 exit 1
108}
109
110while getopts ":s:x" opt; do
111 case $opt in
112 s)
113 SLEEP_TIME=$OPTARG
114 ;;
115 x)
116 set -o xtrace
117 ;;
118 *)
119 usage
120 ;;
121 esac
122done
123shift $((OPTIND-1))
124
125tracker