Files
scylladb/scylla-gdb.py
Avi Kivity 3a69561061 gdb: add 'scylla memory' command
Useful for analyzing memory leaks:

(gdb) scylla memory
objsz spansz    usedobj       memory  wst%
    1   4096          0            0   0.0
    1   4096          0            0   0.0
    1   4096          0            0   0.0
    1   4096          0            0   0.0
    2   4096          0            0   0.0
    2   4096          0            0   0.0
    3   4096          0            0   0.0
    3   4096          0            0   0.0
    4   4096          0            0   0.0
    5   4096          0            0   0.0
    6   4096          0            0   0.0
    7   4096          0            0   0.0
    8   4096        422         8192  58.8
   10   4096          0            0   0.0
   12   4096          0            0   0.0
   14   4096          0         8192  99.8
   16   4096        409         8192  20.1
   20   4096          0            0   0.0
   24   4096          0            0   0.0
   28   4096        653        24576  25.4
   32   4096       1069        36864   7.2
   40   4096          0            0   0.0
   48   4096          0            0   0.0
   56   4096       1228        73728   6.5
   64   4096        616        40960   3.8
   80   4096          0            0   0.0
   96   4096          0            0   0.0
  112   4096        919       110592   5.4
  128   4096        141        24576  26.6
  160   8192          0            0   0.0
  192   8192          0            0   0.0
  224   8192        128        49152  40.1
  256   8192         72        40960  55.0
  320  16384          0            0   0.0
  384  16384          0            0   0.0
  448  16384         60        49152  43.8
  512  16384         29        49152  69.8
  640  32768          0            0   0.0
  768  32768          0            0   0.0
  896  32768         47        98304  55.6
 1024  32768          5        98304  94.8
 1280  65536          0            0   0.0
 1536  65536          0            0   0.0
 1792  65536         31       196608  70.2
 2048  65536          8       196608  91.7
 2560 131072          0            0   0.0
 3072 131072          0            0   0.0
 3584 131072         34       393216  67.4
 4096 131072          0       393216 100.0
 5120 262144          0            0   0.0
 6144 262144          0            0   0.0
 7168 262144         33       786432  68.4
 8192 262144          4       786432  95.8
10240 524288          0            0   0.0
12288 524288          0            0   0.0
14336 524288         33      1572864  68.4
16384 524288          0      1572864 100.0
2015-07-30 10:56:01 +02:00

127 lines
5.1 KiB
Python

import gdb, gdb.printing, uuid
def uint64_t(val):
val = int(val)
if val < 0:
val += 1 << 64
return val
class sstring_printer(gdb.printing.PrettyPrinter):
'print an sstring'
def __init__(self, val):
self.val = val
def to_string(self):
if self.val['u']['internal']['size'] >= 0:
array = self.val['u']['internal']['str']
len = int(self.val['u']['internal']['size'])
return ''.join([chr(array[x]) for x in range(len)])
else:
return self.val['u']['external']['str']
def display_hint(self):
return 'string'
class uuid_printer(gdb.printing.PrettyPrinter):
'print a uuid'
def __init__(self, val):
self.val = val
def to_string(self):
msb = uint64_t(self.val['most_sig_bits'])
lsb = uint64_t(self.val['least_sig_bits'])
return str(uuid.UUID(int=(msb << 64) | lsb))
def display_hint(self):
return 'string'
def build_pretty_printer():
pp = gdb.printing.RegexpCollectionPrettyPrinter('scylla')
pp.add_printer('sstring', r'^basic_sstring<char,.*>$', sstring_printer)
pp.add_printer('uuid', r'^utils::UUID$', uuid_printer)
return pp
gdb.printing.register_pretty_printer(gdb.current_objfile(), build_pretty_printer())
def cpus():
return int(gdb.parse_and_eval('smp::count'))
def find_db(shard):
return gdb.parse_and_eval('debug::db')['_instances']['_M_impl']['_M_start'][shard]
def find_dbs():
return [find_db(shard) for shard in range(cpus())]
def list_unordered_map(map):
kt = map.type.template_argument(0)
vt = map.type.template_argument(1)
value_type = gdb.lookup_type('std::pair<{} const, {}>'.format(kt.name, vt.name))
hashnode_ptr_type = gdb.lookup_type('std::__detail::_Hash_node<' + value_type.name + ', true>').pointer()
h = map['_M_h']
p = h['_M_before_begin']['_M_nxt']
while p:
pc = p.cast(hashnode_ptr_type)['_M_storage']['_M_storage']['__data'].cast(value_type.pointer())
yield (pc['first'], pc['second'].address)
p = p['_M_nxt']
raise StopIteration()
class scylla(gdb.Command):
def __init__(self):
gdb.Command.__init__(self, 'scylla', gdb.COMMAND_USER, gdb.COMPLETE_COMMAND, True)
class scylla_databases(gdb.Command):
def __init__(self):
gdb.Command.__init__(self, 'scylla databases', gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
def invoke(self, arg, from_tty):
for shard in range(cpus()):
db = find_db(shard)
gdb.write('{:5} (database*){}\n'.format(shard, db))
class scylla_keyspaces(gdb.Command):
def __init__(self):
gdb.Command.__init__(self, 'scylla keyspaces', gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
def invoke(self, arg, from_tty):
for shard in range(cpus()):
db = find_db(shard)
keyspaces = db['_keyspaces']
for (key, value) in list_unordered_map(keyspaces):
gdb.write('{:5} {:20} (keyspace*){}\n'.format(shard, key, value))
class scylla_column_families(gdb.Command):
def __init__(self):
gdb.Command.__init__(self, 'scylla column_families', gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
def invoke(self, arg, from_tty):
for shard in range(cpus()):
db = find_db(shard)
cfs = db['_column_families']
for (key, value) in list_unordered_map(cfs):
value = value['_p']['_value'] # it's a lw_shared_ptr
schema = value['_schema']['_p']['_value']
name = str(schema['_raw']['_ks_name']) + '/' + str(schema['_raw']['_cf_name'])
gdb.write('{:5} {} {:45} (column_family*){}\n'.format(shard, key, name, value.address))
class scylla_memory(gdb.Command):
def __init__(self):
gdb.Command.__init__(self, 'scylla memory', gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
def invoke(self, arg, from_tty):
cpu_mem = gdb.parse_and_eval('memory::cpu_mem')
small_pools = cpu_mem['small_pools']
nr = small_pools['nr_small_pools']
page_size = int(gdb.parse_and_eval('memory::page_size'))
gdb.write('{objsize:>5} {span_size:>6} {use_count:>10} {memory:>12} {wasted_percent:>5}\n'
.format(objsize='objsz', span_size='spansz', use_count='usedobj', memory='memory', wasted_percent='wst%'))
for i in range(int(nr)):
sp = small_pools['_u']['a'][i]
object_size = int(sp['_object_size'])
span_size = int(sp['_span_size']) * page_size
free_count = int(sp['_free_count'])
spans_in_use = int(sp['_spans_in_use'])
memory = spans_in_use * span_size
use_count = spans_in_use * int(span_size / object_size) - free_count
wasted = free_count * object_size
wasted_percent = wasted * 100.0 / memory if memory else 0
gdb.write('{objsize:5} {span_size:6} {use_count:10} {memory:12} {wasted_percent:5.1f}\n'
.format(objsize=object_size, span_size=span_size, use_count=use_count, memory=memory, wasted_percent=wasted_percent))
scylla()
scylla_databases()
scylla_keyspaces()
scylla_column_families()
scylla_memory()