utils/memory_leak: add helpers using 3rd-party package "objgraph"
What changed, and why it matters
This commit adds optional developer-only debugging helpers for investigating memory leaks. The new code is not used automatically by Electrum; it is only meant to be run manually from the Qt console by developers. It does not change how wallets, networking, or cryptography work, and it introduces no security vulnerability.
No action needed. This is a benign developer-tooling change. If reviewing further, verify that objgraph remains an optional lazy import and that these helpers are not called from production code paths.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch extends electrum/utils/memory_leak.py with two new helper functions that wrap the third-party objgraph package: debug_memusage_list_all_objects and debug_memusage_dump_random_backref_chain. Both functions import objgraph lazily inside the function body, and the commit message explicitly states Electrum will not take a dependency on objgraph. The functions are only useful when invoked interactively by a developer and are not wired into any runtime path.
Changed components
electrum/utils/memory_leak.pyInspect captured patch +37 / −1
diff --git a/electrum/utils/memory_leak.py b/electrum/utils/memory_leak.py
index 8b276d5..0d3b463 100644
--- a/electrum/utils/memory_leak.py
+++ b/electrum/utils/memory_leak.py
@@ -1,4 +1,6 @@
from collections import defaultdict
+import datetime
+import os
import time
from electrum.util import ThreadJob
@@ -7,7 +9,7 @@ from electrum.util import ThreadJob
class DebugMem(ThreadJob):
'''A handy class for debugging GC memory leaks
- In console:
+ In Qt console:
>>> from electrum.utils.memory_leak import DebugMem
>>> from electrum.wallet import Abstract_Wallet
>>> plugins.add_jobs([DebugMem([Abstract_Wallet,], interval=5)])
@@ -39,3 +41,37 @@ class DebugMem(ThreadJob):
if time.time() > self.next_time:
self.mem_stats()
self.next_time = time.time() + self.interval
+
+
+def debug_memusage_list_all_objects(limit: int = 50) -> list[tuple[str, int]]:
+ """Return a string listing the most common types in memory."""
+ import objgraph # 3rd-party dependency
+ return objgraph.most_common_types(
+ limit=limit,
+ shortnames=False,
+ )
+
+
+def debug_memusage_dump_random_backref_chain(objtype: str) -> str:
+ """Writes a dotfile to cwd, containing the backref chain
+ for a randomly selected object of type objtype.
+
+ Warning: very slow!
+
+ In Qt console:
+ >>> debug_memusage_dump_random_backref_chain("Standard_Wallet")
+
+ To convert to image:
+ $ dot -Tps filename.dot -o outfile.ps
+ """
+ import objgraph # 3rd-party dependency
+ import random
+ timestamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%dT%H%M%SZ")
+ fpath = os.path.abspath(f"electrum_backref_chain_{timestamp}.dot")
+ with open(fpath, "w") as f:
+ objgraph.show_chain(
+ objgraph.find_backref_chain(
+ random.choice(objgraph.by_type(objtype)),
+ objgraph.is_proper_module),
+ output=f)
+ return fpath
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.