commit 53f6fb9876d1b558f61df488d6440f3b5127f011
parent 50755d7db3fb959edf13ace77458aa26b0ea0f41
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:
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/gui/qt/__init__.py b/gui/qt/__init__.py
@@ -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
@@ -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
diff --git a/lib/util.py b/lib/util.py
@@ -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
@@ -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 """
@@ -555,4 +581,3 @@ def check_www_dir(rdir):
if not os.path.exists(path):
print_error("downloading ", URL)
urllib.urlretrieve(URL, path)
-