mirror of
https://github.com/boostorg/unordered.git
synced 2025-05-11 13:34:06 +00:00
Output the open-addressing containers' stats through a GDB xmethod
This commit is contained in:
parent
0bca47c690
commit
5206ac46a3
@ -3,6 +3,9 @@
|
|||||||
# https://www.boost.org/LICENSE_1_0.txt
|
# https://www.boost.org/LICENSE_1_0.txt
|
||||||
|
|
||||||
import gdb.printing
|
import gdb.printing
|
||||||
|
import gdb.xmethod
|
||||||
|
import re
|
||||||
|
import math
|
||||||
|
|
||||||
class BoostUnorderedHelpers:
|
class BoostUnorderedHelpers:
|
||||||
def maybe_unwrap_atomic(n):
|
def maybe_unwrap_atomic(n):
|
||||||
@ -98,6 +101,57 @@ class BoostUnorderedFcaIteratorPrinter:
|
|||||||
def valid(self):
|
def valid(self):
|
||||||
return (self.cpo.to_address(self.val["p"]) != 0) and (self.cpo.to_address(self.val["itb"]["p"]) != 0)
|
return (self.cpo.to_address(self.val["p"]) != 0) and (self.cpo.to_address(self.val["itb"]["p"]) != 0)
|
||||||
|
|
||||||
|
class BoostUnorderedFoaTableCoreCumulativeStatsPrinter:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
return "[stats]"
|
||||||
|
|
||||||
|
def display_hint(self):
|
||||||
|
return "map"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
def generator():
|
||||||
|
members = ["insertion", "successful_lookup", "unsuccessful_lookup"]
|
||||||
|
for member in members:
|
||||||
|
yield "", member
|
||||||
|
yield "", self.val[member]
|
||||||
|
return generator()
|
||||||
|
|
||||||
|
class BoostUnorderedFoaCumulativeStatsPrinter:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
self.n = self.val["n"]
|
||||||
|
self.N = self.val.type.template_argument(0)
|
||||||
|
|
||||||
|
def display_hint(self):
|
||||||
|
return "map"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
def generator():
|
||||||
|
yield "", "count"
|
||||||
|
yield "", self.n
|
||||||
|
|
||||||
|
sequence_stats_data = gdb.lookup_type("boost::unordered::detail::foa::sequence_stats_data")
|
||||||
|
data = self.val["data"]
|
||||||
|
arr = data.address.reinterpret_cast(sequence_stats_data.pointer())
|
||||||
|
def build_string(idx):
|
||||||
|
entry = arr[idx]
|
||||||
|
avg = float(entry["m"])
|
||||||
|
var = float(entry["s"] / self.n) if (self.n != 0) else 0.0
|
||||||
|
dev = math.sqrt(var)
|
||||||
|
return f"{{avg = {avg}, var = {var}, dev = {dev}}}"
|
||||||
|
|
||||||
|
if self.N > 0:
|
||||||
|
yield "", "probe_length"
|
||||||
|
yield "", build_string(0)
|
||||||
|
if self.N > 1:
|
||||||
|
yield "", "num_comparisons"
|
||||||
|
yield "", build_string(1)
|
||||||
|
|
||||||
|
return generator()
|
||||||
|
|
||||||
class BoostUnorderedFoaPrinter:
|
class BoostUnorderedFoaPrinter:
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.val = BoostUnorderedHelpers.maybe_unwrap_reference(val)
|
self.val = BoostUnorderedHelpers.maybe_unwrap_reference(val)
|
||||||
@ -212,6 +266,7 @@ class BoostUnorderedFoaIteratorPrinter:
|
|||||||
def boost_unordered_build_pretty_printer():
|
def boost_unordered_build_pretty_printer():
|
||||||
pp = gdb.printing.RegexpCollectionPrettyPrinter("boost_unordered")
|
pp = gdb.printing.RegexpCollectionPrettyPrinter("boost_unordered")
|
||||||
add_template_printer = lambda name, printer: pp.add_printer(name, f"^{name}<.*>$", printer)
|
add_template_printer = lambda name, printer: pp.add_printer(name, f"^{name}<.*>$", printer)
|
||||||
|
add_concrete_printer = lambda name, printer: pp.add_printer(name, f"^{name}$", printer)
|
||||||
|
|
||||||
add_template_printer("boost::unordered::unordered_map", BoostUnorderedFcaPrinter)
|
add_template_printer("boost::unordered::unordered_map", BoostUnorderedFcaPrinter)
|
||||||
add_template_printer("boost::unordered::unordered_multimap", BoostUnorderedFcaPrinter)
|
add_template_printer("boost::unordered::unordered_multimap", BoostUnorderedFcaPrinter)
|
||||||
@ -230,12 +285,62 @@ def boost_unordered_build_pretty_printer():
|
|||||||
|
|
||||||
add_template_printer("boost::unordered::detail::foa::table_iterator", BoostUnorderedFoaIteratorPrinter)
|
add_template_printer("boost::unordered::detail::foa::table_iterator", BoostUnorderedFoaIteratorPrinter)
|
||||||
|
|
||||||
|
add_concrete_printer("boost::unordered::detail::foa::table_core_cumulative_stats", BoostUnorderedFoaTableCoreCumulativeStatsPrinter)
|
||||||
|
add_template_printer("boost::unordered::detail::foa::cumulative_stats", BoostUnorderedFoaCumulativeStatsPrinter)
|
||||||
|
add_template_printer("boost::unordered::detail::foa::concurrent_cumulative_stats", BoostUnorderedFoaCumulativeStatsPrinter)
|
||||||
|
|
||||||
return pp
|
return pp
|
||||||
|
|
||||||
gdb.printing.register_pretty_printer(gdb.current_objfile(), boost_unordered_build_pretty_printer())
|
gdb.printing.register_pretty_printer(gdb.current_objfile(), boost_unordered_build_pretty_printer())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Writing-an-Xmethod.html
|
||||||
|
class BoostUnorderedFoaGetStatsMethod(gdb.xmethod.XMethod):
|
||||||
|
def __init__(self):
|
||||||
|
gdb.xmethod.XMethod.__init__(self, "get_stats")
|
||||||
|
|
||||||
|
def get_worker(self, method_name):
|
||||||
|
if method_name == "get_stats":
|
||||||
|
return BoostUnorderedFoaGetStatsWorker()
|
||||||
|
|
||||||
|
class BoostUnorderedFoaGetStatsWorker(gdb.xmethod.XMethodWorker):
|
||||||
|
def get_arg_types(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_result_type(self, obj):
|
||||||
|
return gdb.lookup_type("boost::unordered::detail::foa::table_core_cumulative_stats")
|
||||||
|
|
||||||
|
def __call__(self, obj):
|
||||||
|
try:
|
||||||
|
return obj["table_"]["cstats"]
|
||||||
|
except gdb.error:
|
||||||
|
print("Error: Binary was compiled without stats. Recompile with `BOOST_UNORDERED_ENABLE_STATS` defined.")
|
||||||
|
return
|
||||||
|
|
||||||
|
class BoostUnorderedFoaMatcher(gdb.xmethod.XMethodMatcher):
|
||||||
|
def __init__(self):
|
||||||
|
gdb.xmethod.XMethodMatcher.__init__(self, 'BoostUnorderedFoaMatcher')
|
||||||
|
self.methods = [BoostUnorderedFoaGetStatsMethod()]
|
||||||
|
|
||||||
|
def match(self, class_type, method_name):
|
||||||
|
template_name = f"{class_type.strip_typedefs()}".split("<")[0]
|
||||||
|
regex = "^boost::unordered::(unordered|concurrent)_(flat|node)_(map|set)$"
|
||||||
|
if not re.match(regex, template_name):
|
||||||
|
return None
|
||||||
|
|
||||||
|
workers = []
|
||||||
|
for method in self.methods:
|
||||||
|
if method.enabled:
|
||||||
|
worker = method.get_worker(method_name)
|
||||||
|
if worker:
|
||||||
|
workers.append(worker)
|
||||||
|
return workers
|
||||||
|
|
||||||
|
gdb.xmethod.register_xmethod_matcher(None, BoostUnorderedFoaMatcher())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
""" Fancy pointer support """
|
""" Fancy pointer support """
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user