]> git.proxmox.com Git - mirror_spl-debian.git/blob - cmd/splslab/splslab.py
New upstream version 0.7.2
[mirror_spl-debian.git] / cmd / splslab / splslab.py
1 #!/usr/bin/python
2
3 import sys
4 import time
5 import getopt
6 import re
7 import signal
8 from collections import defaultdict
9
10 class Stat:
11 # flag definitions based on the kmem.h
12 NOTOUCH = 1
13 NODEBUG = 2
14 KMEM = 32
15 VMEM = 64
16 SLAB = 128
17 OFFSLAB = 256
18 NOEMERGENCY = 512
19 DEADLOCKED = 16384
20 GROWING = 32768
21 REAPING = 65536
22 DESTROY = 131072
23
24 fdefs = {
25 NOTOUCH : "NTCH",
26 NODEBUG : "NDBG",
27 KMEM : "KMEM",
28 VMEM : "VMEM",
29 SLAB : "SLAB",
30 OFFSLAB : "OFSL",
31 NOEMERGENCY : "NEMG",
32 DEADLOCKED : "DDLK",
33 GROWING : "GROW",
34 REAPING : "REAP",
35 DESTROY : "DSTR"
36 }
37
38 def __init__(self, name, flags, size, alloc, slabsize, objsize):
39 self._name = name
40 self._flags = self.f2str(flags)
41 self._size = size
42 self._alloc = alloc
43 self._slabsize = slabsize
44 self._objsize = objsize
45
46 def f2str(self, flags):
47 fstring = ''
48 for k in Stat.fdefs.keys():
49 if flags & k:
50 fstring = fstring + Stat.fdefs[k] + '|'
51
52 fstring = fstring[:-1]
53 return fstring
54
55 class CumulativeStat:
56 def __init__(self, skey="a"):
57 self._size = 0
58 self._alloc = 0
59 self._pct = 0
60 self._skey = skey
61 self._regexp = \
62 re.compile('(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+');
63 self._stats = defaultdict(list)
64
65 # Add another stat to the dictionary and re-calculate the totals
66 def add(self, s):
67 key = 0
68 if self._skey == "a":
69 key = s._alloc
70 else:
71 key = s._size
72 self._stats[key].append(s)
73 self._size = self._size + s._size
74 self._alloc = self._alloc + s._alloc
75 if self._size:
76 self._pct = self._alloc * 100 / self._size
77 else:
78 self._pct = 0
79
80 # Parse the slab info in the procfs
81 # Calculate cumulative stats
82 def slab_update(self):
83 k = [line.strip() for line in open('/proc/spl/kmem/slab')]
84
85 if not k:
86 sys.stderr.write("No SPL slab stats found\n")
87 sys.exit(1)
88
89 del k[0:2]
90
91 for s in k:
92 if not s:
93 continue
94 m = self._regexp.match(s)
95 if m:
96 self.add(Stat(m.group(1), int(m.group(2),16), int(m.group(3)),
97 int(m.group(4)), int(m.group(5)), int(m.group(6))))
98 else:
99 sys.stderr.write("Error: unexpected input format\n" % s)
100 exit(-1)
101
102 def show_header(self):
103 sys.stdout.write("\n%25s %20s %15s %15s %15s %15s\n\n" % \
104 ("cache name", "flags", "size", "alloc", "slabsize", "objsize"))
105
106 # Show up to the number of 'rows' of output sorted in descending order
107 # by the key specified earlier; if rows == 0, all rows are shown
108 def show(self, rows):
109 self.show_header()
110 i = 1
111 done = False
112 for k in reversed(sorted(self._stats.keys())):
113 for s in self._stats[k]:
114 sys.stdout.write("%25s %20s %15d %15d %15d %15d\n" % \
115 (s._name, s._flags, s._size, s._alloc, \
116 s._slabsize, s._objsize))
117 i = i + 1
118 if rows != 0 and i > rows:
119 done = True
120 break
121 if done:
122 break
123 sys.stdout.write("%25s %36d %15d (%d%%)\n\n" % \
124 ("Totals:", self._size, self._alloc, self._pct))
125
126 def usage():
127 cmd = "Usage: splslab.py [-n|--num-rows] number [-s|--sort-by] " + \
128 "[interval] [count]";
129 sys.stderr.write("%s\n" % cmd)
130 sys.stderr.write("\t-h : print help\n")
131 sys.stderr.write("\t-n : --num-rows N : limit output to N top " +
132 "largest slabs (default: all)\n")
133 sys.stderr.write("\t-s : --sort-by key : sort output in descending " +
134 "order by total size (s)\n\t\tor allocated size (a) " +
135 "(default: a)\n")
136 sys.stderr.write("\tinterval : repeat every interval seconds\n")
137 sys.stderr.write("\tcount : output statistics count times and exit\n")
138
139
140 def main():
141
142 rows = 0
143 count = 0
144 skey = "a"
145 interval = 1
146
147 signal.signal(signal.SIGINT, signal.SIG_DFL)
148
149 try:
150 opts, args = getopt.getopt(
151 sys.argv[1:],
152 "n:s:h",
153 [
154 "num-rows",
155 "sort-by",
156 "help"
157 ]
158 )
159 except getopt.error as e:
160 sys.stderr.write("Error: %s\n" % e.msg)
161 usage()
162 exit(-1)
163
164 i = 1
165 for opt, arg in opts:
166 if opt in ('-n', '--num-rows'):
167 rows = int(arg)
168 i = i + 2
169 elif opt in ('-s', '--sort-by'):
170 if arg != "s" and arg != "a":
171 sys.stderr.write("Error: invalid sorting key \"%s\"\n" % arg)
172 usage()
173 exit(-1)
174 skey = arg
175 i = i + 2
176 elif opt in ('-h', '--help'):
177 usage()
178 exit(0)
179 else:
180 break
181
182 args = sys.argv[i:]
183
184 interval = int(args[0]) if len(args) else interval
185 count = int(args[1]) if len(args) > 1 else count
186
187 i = 0
188 while True:
189 cs = CumulativeStat(skey)
190 cs.slab_update()
191 cs.show(rows)
192
193 i = i + 1
194 if count and i >= count:
195 break
196
197 time.sleep(interval)
198
199 return 0
200
201 if __name__ == '__main__':
202 main()