Tom Stambaugh
Tom Stambaugh

Reputation: 1039

Memory LEAK in matplotlib imshow

I have identified a memory leak in matplotlib.imshow. I am aware of similar questions (like Excessive memory usage in Matplotlib imshow) and I've read the related ironpython thread (https://github.com/ipython/ipython/issues/1623/).

I believe that the code below should (in the absence of a memory leak) consume a constant amount of memory while running. Instead, it grows with each iteration.

I'm running the most recent version I can find (matplotlib-1.2.0rc3.win32-py2.7 and numpy-1.7.0.win32-py2.7), and the problem remains. I'm not keeping the return value of imshow, and in fact I'm explicitly deleting it, so I think the note in IronPython discussion doesn't apply. The behavior is identical with and without the explicit assignment-and-del inside the loop.

I see the same behavior with matplotlib-1.2.0.win32-py2.7.

Each iteration seems to hang onto whatever memory was needed for the image. I've chosen a large (1024x1024) random matrix to make the size of each image interestingly large.

I'm running Win7 pro with 2G of physical RAM, 32-bit python2.7.3 (hence the memory error), and the above numpy and matplotlib packages. The code below fails with a memory error in iteration 440 or so. The windows task manager reports consumption of 1,860,232K when it fails.

Here is code that demonstrates the leak:

IMAGE_SIZE = 1024
import random
RANDOM_MATRIX = []
for i in range(IMAGE_SIZE):
    RANDOM_MATRIX.append([random.randint(0, 100) for each in range(IMAGE_SIZE)])

def exercise(aMatrix, aCount):
    for i in range(aCount):
        anImage = imshow(aMatrix, origin='lower left', vmin=0, vmax=100)
        del(anImage)

if __name__=='__main__':
    from pylab import *
    exercise(RANDOM_MATRIX, 4096)

I can presumably render the image with PIL instead matplotlib. In the absence of a workaround, I do think this is a show-stopper for matplotlib.

Upvotes: 4

Views: 2638

Answers (2)

Camion
Camion

Reputation: 1374

I struggled to make it work because many post talk about this problem, but no one seems to care about providing a working example.

first of all, you should never use the from ... import * syntax, when using a library you didn't make yourself - because, you can never be sure it doesn't declare a symbol which would conflict with yours.

Then, calling set_data is not sufficient to solve this problem - for three reasons :

  1. You didn't mention where this set_data is called from. It is not a normal function but a method from an object... Which object ?
  2. set_data alone won't be sufficient if you do not have something to "activate" the changes. Sometimes it will happen transparently because another plot activates it, but if it doesn't, you will need to call flush_events() by yourself.
  3. Set data won't work if you haven't called imshow() with values it can use to setup it's color map.

Here is a working solution (link):

Upvotes: 1

Tom Stambaugh
Tom Stambaugh

Reputation: 1039

I think I found a workaround, I didn't fully realize how heavyweight imshow is.

The answer is to call imshow just once, then call set_data with RANDOM_MATRIX for each subsequent image.

Problem solved!

Upvotes: 1

Related Questions