I'm seeing a memory leak with calls to subplot.clear() and canvas.draw() on MacOS. The same code shows no leakage on unix.
Here is a simple script that demonstrates the problem. #!/usr/bin/env python from __future__ import division """Demonstrate a memory leak in matplotlib on MacOS with TkAgg Variants: - Comment out subplot.clear(): this reduces the leak by about 4/5 - Comment out canvas.draw(): this reduces the leak by about 1/5 - Comment out both: there should be essentially no leakage The leak rate seems to be affected by the update rate (larger update interval causes lower leakage), which suggests it's not a simple "x amount of leakage per call". """ import resource import time import Tkinter import matplotlib from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg class MemoryLeaker(Tkinter.Frame): """Demonstrate a memory leak in matplotlib """ def __init__(self, master, updateInterval=0.1, updatesPerReport=25): """Construct a MemoryLeaker Inputs: - master: master widget - updateInterval: interval at which subplot.clear and canvas.draw are called - updatesPerReport: number of updates between memory reports """ Tkinter.Frame.__init__(self, master) self._updateInterval = float(updateInterval) self._updatesPerReport = int(updatesPerReport) self.figure = matplotlib.figure.Figure(figsize=(8, 2), frameon=True) self.canvas = FigureCanvasTkAgg(self.figure, self) self.canvas.get_tk_widget().grid(row=0, column=0, sticky="news") self.subplot = self.figure.add_subplot(1, 1, 1) print "time max RSS leak rate" print "(sec) (kb) (kb/sec)" self._prevTime = time.time() self._prevMem = float("nan") self._reportCount = 0 self.updatePlot() def updatePlot(self): """Update the plot; calls itself at the update interval """ if self._reportCount == 0: self.reportMem() self._reportCount = (self._reportCount + 1) % self._updatesPerReport self.subplot.clear() self.canvas.draw() self.after(int(self._updateInterval * 1000), self.updatePlot) def reportMem(self): currTime = time.time() dTime = currTime - self._prevTime res = resource.getrusage(resource.RUSAGE_SELF) currMem = res.ru_maxrss / 1024 # maximum resident set size utilized (in kb) leakRate = (currMem - self._prevMem) / dTime self._prevTime = currTime self._prevMem = currMem print "%6.1f %6d %6.1f" % (dTime, currMem, leakRate) if __name__ == "__main__": root = Tkinter.Tk() wdg = MemoryLeaker(root, updateInterval=0.1, updatesPerReport=25) wdg.pack(expand=True, fill="both") root.mainloop() P.S. my current setup is: - MacOS 10.9 - python.org python 2.7.8 - matploblib 1.3.1 - a pre-release of Tcl/Tk 8.5.17 but I've seen this on many earlier versions, as well I have not tried it with matplotlib 1.4.1 yet (due to problems packaging that with py2app). ------------------------------------------------------------------------------ _______________________________________________ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users