2"""Process a ref debug log for memory usage
4 This will provide information about total and peak
7 See http://www.asterisk.org for more information about
8 the Asterisk project. Please do not directly contact
9 any of the maintainers of this project for assistance;
10 the project provides a web site, mailing lists and IRC
11 channels for your use.
13 This program is free software, distributed under the terms of
14 the GNU General Public License Version 2. See the LICENSE file
15 at the top of the source tree.
17 Copyright (C) 2018, CFWare, LLC
18 Corey Farrell <git@cfware.com>
21from __future__
import print_function
25from optparse
import OptionParser
29 """Create statistics object"""
39 """Update statistics objects"""
46 if current[key] > peak[key]:
47 peak[key] = current[key]
51 """The routine that kicks off processing a ref file"""
58 filename = options.filepath
60 with open(filename,
'r')
as ref_file:
62 if 'constructor' not in line
and 'destructor' not in line:
67 tokens = line.strip().split(
',', 7)
70 if 'constructor' in state:
71 split_state = state.split(
"**")
72 if len(split_state) < 4:
73 print(
"File does not contain object size information", file=sys.stderr)
76 obj_type =
'%s:%s:%s' % (tokens[3], tokens[4], tokens[5])
77 if obj_type
not in object_types:
78 object_types[obj_type] = {
83 overhead = int(split_state[2])
84 user_data = int(split_state[3])
85 obj = objects[addr] = {
87 'user_data': user_data,
93 if addr
not in objects:
99 obj_type = obj[
'obj_type']
100 if '**lock-state:unused**' in state:
101 object_types[obj_type][
'unused'] += 1
102 elif '**lock-state:used**' in state:
103 object_types[obj_type][
'used'] += 1
106 update_stats(current, peak, total,
'count', direction, 1)
107 update_stats(current, peak, total,
'overhead', direction, obj[
'overhead'])
108 update_stats(current, peak, total,
'user_data', direction, obj[
'user_data'])
109 update_stats(current, peak, total,
'totalmem', direction, obj[
'overhead'] + obj[
'user_data'])
111 print(
"Total usage statistics:")
112 print(
"%20s: %d" % (
"Count", total[
'count']))
113 print(
"%20s: %d" % (
"Total Memory (k)", total[
'totalmem'] / 1024))
114 print(
"%20s: %d (%.2f%%)" % (
"Overhead (k)", total[
'overhead'] / 1024, total[
'overhead'] * 100.0 / total[
'totalmem']))
115 print(
"%20s: %d" % (
"User Data (k)", total[
'user_data'] / 1024))
117 print(
"Peak usage statistics:")
118 print(
"%20s: %d" % (
"Count", peak[
'count']))
119 print(
"%20s: %d" % (
"Total Memory (k)", peak[
'totalmem'] / 1024))
120 print(
"%20s: %d (%.2f%%)" % (
"Overhead (k)", peak[
'overhead'] / 1024, peak[
'overhead'] * 100.0 / peak[
'totalmem']))
121 print(
"%20s: %d" % (
"User Data (k)", peak[
'user_data'] / 1024))
124 lockbyobj = {
'used': 0,
'total': 0}
125 lockbytype = {
'used': 0,
'total': 0}
126 for (allocator, info)
in object_types.items():
127 lockbyobj[
'used'] += info[
'used']
128 lockbyobj[
'total'] += info[
'used'] + info[
'unused']
130 if info[
'used'] != 0:
131 lockbytype[
'used'] += 1
132 elif info[
'unused'] == 0:
135 lockbytype[
'total'] += 1
137 print(
"Lock usage statistics:")
138 print(
"%20s: %d of %d used (%.2f%%)" % (
142 lockbyobj[
'used'] * 100.0 / lockbyobj[
'total']))
143 print(
"%20s: %d of %d used (%.2f%%)" % (
147 lockbytype[
'used'] * 100.0 / lockbytype[
'total']))
151 """Main entry point for the script"""
158 parser = OptionParser()
160 parser.add_option(
"-f",
"--file", action=
"store", type=
"string",
161 dest=
"filepath", default=
"/var/log/asterisk/refs",
162 help=
"The full path to the refs file to process")
164 (options, args) = parser.parse_args(argv)
166 if not os.path.isfile(options.filepath):
167 print(
"File not found: %s" % options.filepath, file=sys.stderr)
172 except (KeyboardInterrupt, SystemExit, IOError):
173 print(
"File processing cancelled", file=sys.stderr)
179if __name__ ==
"__main__":
180 sys.exit(
main(sys.argv))
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
def update_stats(current, peak, total, key, direction, delta)
def process_file(options)