Author: bugman Date: Wed Feb 4 11:15:48 2015 New Revision: 27504 URL: http://svn.gna.org/viewcvs/relax?rev=27504&view=rev Log: Created the memory_leak_test_GUI_uf.py development script. This is to help in tracking down memory leaks in the relax GUI user functions. Instead of using a debugging Python version and guppy (wxPython doesn't seem to work with these), the pympler Python package and its muppy module is used to produce a memory usage printout. Added: trunk/devel_scripts/memory_leak_test_GUI_uf.py - copied, changed from r27503, trunk/devel_scripts/memory_leak_test_relax_fit.py Copied: trunk/devel_scripts/memory_leak_test_GUI_uf.py (from r27503, trunk/devel_scripts/memory_leak_test_relax_fit.py) URL: http://svn.gna.org/viewcvs/relax/trunk/devel_scripts/memory_leak_test_GUI_uf.py?p2=trunk/devel_scripts/memory_leak_test_GUI_uf.py&p1=trunk/devel_scripts/memory_leak_test_relax_fit.py&r1=27503&r2=27504&rev=27504&view=diff ============================================================================== --- trunk/devel_scripts/memory_leak_test_relax_fit.py (original) +++ trunk/devel_scripts/memory_leak_test_GUI_uf.py Wed Feb 4 11:15:48 2015 @@ -21,33 +21,171 @@ """Script for relaxation curve fitting. -Run with a debugging compiled version of Python, eg: - -/data/python/pydebug/bin/python relax devel_scripts/memory_leak_test_relax_fit.py - -and build the C module with: - -gcc -o target_functions/c_chi2.os -c -I/data/python/pydebug/include/python2.7/ -fPIC target_functions/c_chi2.c -gcc -o target_functions/exponential.os -c -I/data/python/pydebug/include/python2.7/ -fPIC target_functions/exponential.c -gcc -o target_functions/exponential_inv.os -c -I/data/python/pydebug/include/python2.7/ -fPIC target_functions/exponential_inv.c -gcc -o target_functions/exponential_sat.os -c -I/data/python/pydebug/include/python2.7/ -fPIC target_functions/exponential_sat.c -gcc -o target_functions/relax_fit.os -c -I/data/python/pydebug/include/python2.7/ -fPIC target_functions/relax_fit.c -gcc -o target_functions/relax_fit.so -shared target_functions/c_chi2.os target_functions/exponential.os target_functions/exponential_inv.os target_functions/exponential_sat.os target_functions/relax_fit.os +Run with a normal version of Python, i.e. a debugging version is not needed, with: + +/data/python/bin/python relax devel_scripts/memory_leak_test_relax_fit.py """ - # Python module imports. from os import sep +from pympler import muppy import sys - -# Check. -if not hasattr(sys, 'gettotalrefcount'): - print("This is not a debugging compiled version of Python, quitting!") - sys.exit() +import wx # relax module imports. from data_store import Relax_data_store; ds = Relax_data_store() +from gui import relax_gui +from gui.controller import Controller +from gui.fonts import font +from gui.interpreter import Interpreter +from gui.uf_objects import Uf_storage; uf_store = Uf_storage() +from lib.errors import RelaxError from status import Status; status = Status() +from user_functions.data import Uf_info; uf_info = Uf_info() + + + +class Controller: + """Dummy relax controller.""" + + def __init__(self): + self.log_panel = Log_panel() + + + +class Log_panel: + """Dummy relax controller log panel.""" + + def on_goto_end(self, arg1): + """Dummy function.""" + + + +class Testing_frame(wx.Frame): + """Testing frame.""" + + def __init__(self, parent, title): + """Set up a minimal relax GUI.""" + + # Initialise the frame. + wx.Frame.__init__(self, parent, title=title, size=(200,100)) + + # Set up a pseudo-relax GUI. + app = wx.GetApp() + app.gui = self + + # Set up some standard interface-wide fonts. + font.setup() + + # Initialise the special interpreter thread object. + self.interpreter = Interpreter() + + # Build the controller, but don't show it. + self.controller = Controller() + + self.test() + self.Show(True) + + + def _execute_uf(self, *args, **kargs): + """Execute the given user function. + + @keyword uf_name: The name of the user function. + @type uf_name: str + """ + + # Checks. + if 'uf_name' not in kargs: + raise RelaxError("The user function name argument 'uf_name' has not been supplied.") + + # Process the user function name. + uf_name = kargs.pop('uf_name') + + # Get the user function data object. + uf_data = uf_info.get_uf(uf_name) + + # Convert the args into keyword args. + for i in range(len(args)): + # The keyword name for this arg. + name = uf_data.kargs[i]['name'] + + # Check. + if name in kargs: + raise RelaxError("The argument '%s' clashes with the %s keyword argument of '%s'." % (arg[i], name, kargs[name])) + + # Set the keyword arg. + kargs[name] = args[i] + + # Add the keyword args not supplied, using the default value. + for i in range(len(uf_data.kargs)): + # Alias. + arg = uf_data.kargs[i] + + # Already set. + if arg['name'] in kargs: + continue + + # Set the default. + kargs[arg['name']] = arg['default'] + + # Merge the file and directory args, as needed. + for i in range(len(uf_data.kargs)): + # Alias. + arg = uf_data.kargs[i] + + # File selection and associated directory arg. + if arg['arg_type'] == 'dir' and arg['name'] in kargs: + # Find the associated file selection arg name. + for j in range(len(uf_data.kargs)): + if uf_data.kargs[j]['arg_type'] == 'file sel': + file_sel_name = uf_data.kargs[j]['name'] + + # Prepend the directory to the file, if needed and supplied. + if file_sel_name in kargs and kargs[arg['name']]: + kargs[file_sel_name] = kargs[arg['name']] + sep + kargs[file_sel_name] + + # Remove the directory argument. + kargs.pop(arg['name']) + + # The user function object. + uf = uf_store[uf_name] + + # Force synchronous operation of the user functions. + status.gui_uf_force_sync = True + + # Call the GUI user function object with all keyword args, but do not execute the wizard. + uf(wx_wizard_run=False, **kargs) + + # Execute the user function, by mimicking a click on 'ok'. + uf.wizard._ok() + + # Restore the synchronous or asynchronous operation of the user functions so the GUI can return to normal. + status.gui_uf_force_sync = False + + # Destroy the user function object. + uf.Destroy() + + + def show_controller(self, arg1): + """Dummy function.""" + + + def test(self): + """Run the tests.""" + + # Minimise via the GUI user function. + file = open('muppy_log', 'w') + for i in range(10000): + self._execute_uf(uf_name='minimise.execute', min_algor='simplex', constraints=False) + if not i % 100: + file.write("Iteration %i\n" % i) + file.write("Muppy heap:\n%s\n\n\n") + for line in muppy.summary.format_(muppy.summary.summarize(muppy.get_objects())): + file.write("%s\n" % line) + file.write("\n\n\n") + file.flush() + + print("Finished :)") # Missing intensity type (allow this script to run outside of the system test framework). @@ -131,17 +269,8 @@ # Grid search. minimise.grid_search(inc=11) -# Minimise. -from guppy import hpy -file = open('guppy_log', 'w') -for i in range(10000): - minimise.execute('simplex', constraints=False) - if not i % 100: - file.write("Iteration %i\n" % i) - file.write("Reference counts:\n%s\n\n" % sys.gettotalrefcount()) - h = hpy() - file.write("Guppy heap:\n%s\n\n\n" % h.heap()) - file.flush() - - -print("Finished :)") +# Set up the GUI. +app = wx.App(False) +frame = Testing_frame(None, "GUI memory test") +frame.Show(True) +app.MainLoop()