Hello,
I'm PhD student in Bioinformatic and I'm working on a project using matplotlib and Tkinter but I've got a big problem of memory leak using these modules. I'll be very grateful if you could help me to solve this problem.
Here is the link explaining what happends, with a reduced script:
Thank you in advance,
Sincerly,
Pierre Garcia, PhD Student
--------- Bases Moléculaires et Structurales des Systèmes infectieux-UMR5086 Institut de Biologie et Chimie des Protéines 7 passage du Vercors 69 367 Lyon cedex 07 --------- Laboratoire de Biométrie et Biologie Evolutive-UMR5558 UCBL Lyon 1 -Bât. Grégory Mendel 43 bd du 11 novembre 1918 69622 VILLEURBANNE cedex
_______________________________________________ Matplotlib-users mailing list [hidden email] https://mail.python.org/mailman/listinfo/matplotlib-users |
It is likely there things are not being garbage collected due to either a missed reference surviving or the circular references between the various objects is delaying gc from collecting them (I do not recall the details exactly off the top of my head, but running gc manually with more generations may help). However, if you are embedding in a GUI you are probably better off just doing the embedding directly (and skipping `pyplot` entirely, see https://matplotlib.org/examples/user_interfaces/embedding_in_tk.html ). Re-using the Figures / Axes / Artists to update the data (rather than starting from scratch every time) may also prevent the memory leaks _and_ give you a performance boost. Please subscribe to the list so that you can post without moderation. Tom On Sat, Aug 5, 2017 at 12:36 PM GARCIA PIERRE SIMON p0904379 <[hidden email]> wrote:
_______________________________________________ Matplotlib-users mailing list [hidden email] https://mail.python.org/mailman/listinfo/matplotlib-users |
The stackoverflow posting notes that mpl v1.1.1 was used, which is 5 years old. I am pretty sure we have made a lot of memory leak fixes since then. I noted as such on SO. Ben RootOn Sat, Aug 5, 2017 at 7:48 PM, Thomas Caswell <[hidden email]> wrote:
_______________________________________________ Matplotlib-users mailing list [hidden email] https://mail.python.org/mailman/listinfo/matplotlib-users |
Did the rate of memory leak change? On Thu, Oct 19, 2017 at 10:26 AM, GARCIA PIERRE SIMON p0904379 <[hidden email]> wrote:
_______________________________________________ Matplotlib-users mailing list [hidden email] https://mail.python.org/mailman/listinfo/matplotlib-users |
Have you tried manually adding calls to `gc.collect(2)`? That may help to clean up any circular reference cycles hanging around. Can you replicate this with a simpler script? The code on SO is hard to follow. Tom On Thu, Oct 19, 2017 at 10:56 AM GARCIA PIERRE SIMON p0904379 <[hidden email]> wrote:
_______________________________________________ Matplotlib-users mailing list [hidden email] https://mail.python.org/mailman/listinfo/matplotlib-users |
I think there was a bug in how you were capturing the clearing the children of the top level frame. Tweaking it a bit I can reproduce the leaking, but not on every cycle: from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import matplotlib.patches as patches # from Tkinter import Tk, Canvas, Frame, Label, Button from six.moves import tkinter as Tk import gc import resource from matplotlib.figure import Figure import sys list_fig_g = [] list_wid_g = [] def launcher(list_wid, list_fig, frame): print('Memory usage: %s (kb)' % resource.getrusage(resource.RUSAGE_SELF).ru_maxrss,) for f in list_fig: f.clf() f.clear() f._master = None del f list_fig.clear() for i in list_wid: print(i, sys.getrefcount(i)) r = i.winfo_toplevel() i.grid_forget() i.destroy() for k in ('<MouseWheel>', '<Destroy>'): r.unbind(k) print(i, sys.getrefcount(i)) del i list_wid.clear() fig1 = Figure(figsize=(1, 1)) ax1 = fig1.add_subplot(111, aspect='equal') ax1.add_patch( patches.Arrow( 0, # x -0, # y 1, # dx 0, # dy width=1, ) ) list_fig.append(fig1) # this seems to be the first line that leaks memory # but not _always_ canvas = FigureCanvasTkAgg(fig1, master=None) t1, t2, w, h = fig1.bbox.bounds widget = canvas.get_tk_widget() # widget = Tk.Canvas( # master=frame, width=w, height=h, borderwidth=0, # highlightthickness=0) # w2 = Tk.PhotoImage( # master=widget, width=int(w), height=int(h)) # widget.create_image(w//2, h//2, image=w2) widget.grid(row=0, column=1) widget.focus_set() list_wid.extend(frame.winfo_children()) # print(w) # print('gc: ', gc.collect(2)) gc.collect(2) # canvas.draw() print('Memory usage: %s (kb)' % resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) print() def bulk(list_wid, list_fig, frame): for j in range(100): launcher(list_wid, list_fig, frame) root = Tk.Tk() Entete5 = Tk.Label(root, width=20, height=1).grid(row=0, column=1) fond = Tk.Canvas(root, width=800, height=200) fond.grid(row=1, column=1) frame_g = Tk.Frame(fond, width=80, height=10) frame_g.grid(row=0, column=1) fond.create_window(0, 0, window=frame_g) Load = Tk.Button(root, text="Load", command=lambda: launcher(list_wid_g, list_fig_g, frame_g)) go = Tk.Button(root, text="bulk", command=lambda: bulk(list_wid_g, list_fig_g, frame_g)) Load.grid(row=7, column=4) go.grid(row=6, column=4) list_wid = frame_g.winfo_children() root.mainloop() (I also added a 'bulk' button to run 100 iterations). I tried just creating a FigureCanvasAgg object (the super-class of FigureCanvasTkAgg) and that seems not to leak. Doing most of the tk work that FigureCanvasTkAgg does not seem to leak. It looks like it is the callbacks that are registered to handle mouse and key board events, deleteing them from the __init__ seems to prevent the leak! Not sure what the right way to clean those up is though, but at least this is pointing the right direction! Tom On Thu, Oct 19, 2017 at 12:18 PM GARCIA PIERRE SIMON p0904379 <[hidden email]> wrote:
_______________________________________________ Matplotlib-users mailing list [hidden email] https://mail.python.org/mailman/listinfo/matplotlib-users |
Free forum by Nabble | Edit this page |