2017-05-01 03:26:56 +03:00
#!/usr/bin/env python3
2017-11-18 19:32:46 +03:00
# SPDX-License-Identifier: LGPL-2.1+
2014-10-15 03:31:23 +04:00
2018-08-25 19:41:42 +03:00
from __future__ import print_function
2014-10-15 03:31:23 +04:00
import gdb
class sd_dump_hashmaps ( gdb . Command ) :
" dump systemd ' s hashmaps "
def __init__ ( self ) :
super ( sd_dump_hashmaps , self ) . __init__ ( " sd_dump_hashmaps " , gdb . COMMAND_DATA , gdb . COMPLETE_NONE )
def invoke ( self , arg , from_tty ) :
d = gdb . parse_and_eval ( " hashmap_debug_list " )
all_entry_sizes = gdb . parse_and_eval ( " all_entry_sizes " )
all_direct_buckets = gdb . parse_and_eval ( " all_direct_buckets " )
uchar_t = gdb . lookup_type ( " unsigned char " )
ulong_t = gdb . lookup_type ( " unsigned long " )
debug_offset = gdb . parse_and_eval ( " (unsigned long)&((HashmapBase*)0)->debug " )
2018-08-25 19:41:42 +03:00
print ( " type, hash, indirect, entries, max_entries, buckets, creator " )
2014-10-15 03:31:23 +04:00
while d :
h = gdb . parse_and_eval ( " (HashmapBase*)((char*) %d - %d ) " % ( int ( d . cast ( ulong_t ) ) , debug_offset ) )
if h [ " has_indirect " ] :
storage_ptr = h [ " indirect " ] [ " storage " ] . cast ( uchar_t . pointer ( ) )
n_entries = h [ " indirect " ] [ " n_entries " ]
n_buckets = h [ " indirect " ] [ " n_buckets " ]
else :
storage_ptr = h [ " direct " ] [ " storage " ] . cast ( uchar_t . pointer ( ) )
n_entries = h [ " n_direct_entries " ]
n_buckets = all_direct_buckets [ int ( h [ " type " ] ) ] ;
t = [ " plain " , " ordered " , " set " ] [ int ( h [ " type " ] ) ]
2018-08-25 19:41:42 +03:00
print ( " {} , {} , {} , {} , {} , {} , {} ( {} : {} ) " . format ( t , h [ " hash_ops " ] , bool ( h [ " has_indirect " ] ) , n_entries , d [ " max_entries " ] , n_buckets , d [ " func " ] , d [ " file " ] , d [ " line " ] ) )
2014-10-15 03:31:23 +04:00
if arg != " " and n_entries > 0 :
dib_raw_addr = storage_ptr + ( all_entry_sizes [ h [ " type " ] ] * n_buckets )
histogram = { }
for i in xrange ( 0 , n_buckets ) :
dib = int ( dib_raw_addr [ i ] )
histogram [ dib ] = histogram . get ( dib , 0 ) + 1
for dib in sorted ( iter ( histogram ) ) :
if dib != 255 :
2018-08-25 19:41:42 +03:00
print ( " {:>3} {:>8} {} of entries " . format ( dib , histogram [ dib ] , 100.0 * histogram [ dib ] / n_entries ) )
2014-10-15 03:31:23 +04:00
else :
2018-08-25 19:41:42 +03:00
print ( " {:>3} {:>8} {} of slots " . format ( dib , histogram [ dib ] , 100.0 * histogram [ dib ] / n_buckets ) )
print ( " mean DIB of entries: {} " . format ( sum ( [ dib * histogram [ dib ] for dib in iter ( histogram ) if dib != 255 ] ) * 1.0 / n_entries ) )
2014-10-15 03:31:23 +04:00
blocks = [ ]
current_len = 1
prev = int ( dib_raw_addr [ 0 ] )
for i in xrange ( 1 , n_buckets ) :
dib = int ( dib_raw_addr [ i ] )
if ( dib == 255 ) != ( prev == 255 ) :
if prev != 255 :
blocks + = [ [ i , current_len ] ]
current_len = 1
else :
current_len + = 1
prev = dib
if prev != 255 :
blocks + = [ [ i , current_len ] ]
# a block may be wrapped around
if len ( blocks ) > 1 and blocks [ 0 ] [ 0 ] == blocks [ 0 ] [ 1 ] and blocks [ - 1 ] [ 0 ] == n_buckets - 1 :
blocks [ 0 ] [ 1 ] + = blocks [ - 1 ] [ 1 ]
blocks = blocks [ 0 : - 1 ]
2018-08-25 19:41:42 +03:00
print ( " max block: {} " . format ( max ( blocks , key = lambda a : a [ 1 ] ) ) )
print ( " sum block lens: {} " . format ( sum ( b [ 1 ] for b in blocks ) ) )
print ( " mean block len: {} " . format ( ( 1.0 * sum ( b [ 1 ] for b in blocks ) / len ( blocks ) ) ) )
2014-10-15 03:31:23 +04:00
d = d [ " debug_list_next " ]
sd_dump_hashmaps ( )