tAdd a GC debugger Add commented-out GC debugging step - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 53f6fb9876d1b558f61df488d6440f3b5127f011 DIR parent 50755d7db3fb959edf13ace77458aa26b0ea0f41 HTML Author: Neil Booth <kyuupichan@gmail.com> Date: Fri, 13 Nov 2015 23:11:43 +0900 Add a GC debugger Add commented-out GC debugging step Diffstat: M gui/qt/__init__.py | 8 ++++++++ M lib/util.py | 27 ++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) --- DIR diff --git a/gui/qt/__init__.py b/gui/qt/__init__.py t@@ -34,6 +34,10 @@ from electrum.plugins import run_hook from electrum import SimpleConfig, Wallet, WalletStorage from electrum.paymentrequest import InvoiceStore from electrum.contacts import Contacts +from electrum.synchronizer import Synchronizer +from electrum.verifier import SPV +from electrum.util import DebugMem +from electrum.wallet import Abstract_Wallet from installwizard import InstallWizard t@@ -64,6 +68,10 @@ class ElectrumGui: def __init__(self, config, network, plugins): set_language(config.get('language')) + # Uncomment this call to verify objects are being properly + # GC-ed when windows are closed + #network.add_jobs([DebugMem([Abstract_Wallet, SPV, Synchronizer, + # ElectrumWindow], interval=5)]) self.network = network self.config = config self.plugins = plugins DIR diff --git a/lib/util.py b/lib/util.py t@@ -1,6 +1,7 @@ import os, sys, re, json import platform import shutil +from collections import defaultdict from datetime import datetime from decimal import Decimal import traceback t@@ -45,6 +46,31 @@ class ThreadJob(PrintError): """Called periodically from the thread""" pass +class DebugMem(ThreadJob): + '''A handy class for debugging GC memory leaks''' + def __init__(self, classes, interval=30): + self.next_time = 0 + self.classes = classes + self.interval = interval + + def mem_stats(self): + import gc + self.print_error("Start memscan") + gc.collect() + objmap = defaultdict(list) + for obj in gc.get_objects(): + for class_ in self.classes: + if isinstance(obj, class_): + objmap[class_].append(obj) + for class_, objs in objmap.items(): + self.print_error("%s: %d" % (class_.__name__, len(objs))) + self.print_error("Finish memscan") + + def run(self): + if time.time() > self.next_time: + self.mem_stats() + self.next_time = time.time() + self.interval + class DaemonThread(threading.Thread, PrintError): """ daemon thread that terminates cleanly """ t@@ -555,4 +581,3 @@ def check_www_dir(rdir): if not os.path.exists(path): print_error("downloading ", URL) urllib.urlretrieve(URL, path) -