Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

close() not releasing memory after matplotlib savefig

I'm running a python program which replots a graph every few minutes, but every time it runs the memory it uses goes up a little bit, and soon the raspberry pi I'm using slows to a crawl.

Here's the relevant piece of code:

import matplotlib.pyplot as plt
import matplotlib.dates as md
from memory_profiler import profile

@profile
def plotter(file_name, plot_name):
    with open(filen_name, 'r') as readings:
        reader = csv.reader(readings, delimiter=',')
        data = [row for row in reader]

    plt.plot(data[2], data[0])
    ax = gca()
    xfmt = md.DateFormatter('%H:%M') # xaxis is datetimes
    ax.xaxis.set_major_formatter(xfmt)
    plt.legend()

    plt.savefig(plot_name, transparent=True)
    plt.clf()
    plt.cla()
    plt.close()

And the function is called with something like:

 while True:
     plotter(file_name, plot_name)
     sleep(100)

The memory_profiler spits out nice output, but it always looks like this:

Line #    Mem usage    Increment   Line Contents
================================================
38     36.2 MiB      0.6 MiB       plt.savefig(plot_name, transparent=True)
39     36.2 MiB      0.0 MiB       plt.clf()
40     36.2 MiB      0.0 MiB       plt.cla()
41     36.2 MiB      0.0 MiB       plt.close()

(The rest of the function doesn't increase memory usage.)
The memory is incrementing up at savefig(), but is never released despite the various ways I've tried to close the figure. Anyone know why the close() doesn't release the memory?


Edit:
I've tried another method.

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot( some arguments)
fig.savefig(filename)

plt.close('all')
del ax, fig

This doesn't decrement the memory usage either.


Edit 2:
From this answer elsewhere (Create a figure that is reference counted) I've tried the following:

from matplotlib.backends.backend_svg import FigureCanvas
from matplotlib.figure import Figure

fig = Figure()
canvas = FigureCanvas(fig)
ax = fig.add_subplot(111)
ax.plot etc...
fig.savefig(file_name)
plt.close('all')

This also doesn't seem to work. Memory still increasing monotonically and always at the savefig line of the function.

like image 498
thosphor Avatar asked Oct 25 '17 13:10

thosphor


People also ask

Does Matplotlib overwrite Savefig?

Save this question. Show activity on this post. It will create the figure the first time the code is run.

What is Matplotlib use (' AGG ')?

The last, Agg, is a non-interactive backend that can only write to files. It is used on Linux, if Matplotlib cannot connect to either an X display or a Wayland display.


1 Answers

I encountered the same issue. After looking around I found a solution: you need to close the fig AND all windows.

import matplotlib.pylab as plt

fig,ax = plt.subplots(1)
plt.plot(X, Y)
fig.savefig(img_name)
fig.clf()
plt.close()

After closing both the plot and figure, my memory stayed at a more or less constant level.

You can also close the axis using:

ax.cla()
like image 171
Marc-V Avatar answered Oct 22 '22 13:10

Marc-V