1
0
mirror of https://github.com/systemd/systemd.git synced 2025-08-29 01:49:55 +03:00
Files
systemd/tools/gdb-sd_dump_hashmaps.py
Zbigniew Jędrzejewski-Szmek 8aedfd979f tools: make all .py program files executable
All those files are standalone programs that can be executed directly.
Some .py files were marked executable, others weren't, probably accidentally.
Mark them all as executable in preparation for subsequent changes.
2025-07-25 12:33:13 +02:00

79 lines
3.4 KiB
Python
Executable File

#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later
# pylint: disable=consider-using-f-string
import gdb
class sd_dump_hashmaps(gdb.Command):
"dump systemd's hashmaps"
def __init__(self):
super().__init__("sd_dump_hashmaps", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
def invoke(self, arg, _from_tty):
d = gdb.parse_and_eval("hashmap_debug_list")
hashmap_type_info = gdb.parse_and_eval("hashmap_type_info")
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")
print("type, hash, indirect, entries, max_entries, buckets, creator")
while d:
h = gdb.parse_and_eval(f"(HashmapBase*)((char*){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 = hashmap_type_info[h["type"]]["n_direct_buckets"]
t = ["plain", "ordered", "set"][int(h["type"])]
print(f'{t}, {h["hash_ops"]}, {bool(h["has_indirect"])}, {n_entries}, {d["max_entries"]}, {n_buckets}')
if arg != "" and n_entries > 0:
dib_raw_addr = storage_ptr + hashmap_type_info[h["type"]]["entry_size"] * n_buckets
histogram = {}
for i in range(0, n_buckets):
dib = int(dib_raw_addr[i])
histogram[dib] = histogram.get(dib, 0) + 1
for dib in sorted(histogram):
if dib != 255:
print(f"{dib:>3} {histogram[dib]:>8} {float(histogram[dib]/n_entries):.0%} of entries")
else:
print(f"{dib:>3} {histogram[dib]:>8} {float(histogram[dib]/n_buckets):.0%} of slots")
s = sum(dib*count for (dib, count) in histogram.items() if dib != 255) / n_entries
print(f"mean DIB of entries: {s}")
blocks = []
current_len = 1
prev = int(dib_raw_addr[0])
for i in range(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]
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(sum(b[1] for b in blocks) / len(blocks)))
d = d["debug_list_next"]
sd_dump_hashmaps()