From: Joe <gar...@us...> - 2005-01-18 21:40:21
|
Hello devels, I chose to use matplotlib for a restaurant simulation. It supplied all the features I needed and I was pleasantly surprised. However the people I was doing this project for mentioned that the simulation slowed down to a crawl 10 or so minutes into the simulation. It sounded like a memory leak to me so I investigated and found a 100 KB/sec leak in Windows (via the interpreter as well as frozen with py2exe) as well as in Linux. I narrowed it down to a part of the code where I updated xlim and ylim via Axes::set_xlim, Axes::set_ylim. Commenting that part out yielded no leak, however I lost some critical functionality in my charts (which behave like the Windows Task Manager resource monitor graphs). So I really need this fixed. I will send shortly a test case which replicates the problem. Since the maintainer is out on vacation, I was also wondering if anyone knew enough about the internals of matplotlib that they could give me an idea of which modules (Python or otherwise) are affected by Axes::set_xlim and Axes::set_ylim. Joe |
From: John H. <jdh...@ac...> - 2005-01-19 02:31:31
|
>>>>> "Joe" == Joe <gar...@us...> writes: Joe> Hello devels, I chose to use matplotlib for a restaurant Joe> simulation. It supplied all the features I needed and I was Joe> pleasantly surprised. However the people I was doing this Joe> project for mentioned that the simulation slowed down to a Joe> crawl 10 or so minutes into the simulation. It sounded like Joe> a memory leak to me so I investigated and found a 100 KB/sec Joe> leak in Windows (via the interpreter as well as frozen with Joe> py2exe) as well as in Linux. I narrowed it down to a part of Joe> the code where I updated xlim and ylim via Axes::set_xlim, Joe> Axes::set_ylim. Commenting that part out yielded no leak, So you're doing animation right? Are you using images, eg imshow? I just fixed a memory leak in image resizing that amounts to about 200K/resize -- the changes are in CVS. Of course on windows it's hard to test because the changes are in extension code, and require building on win32. The instructions for building on win32 are in the file setupext.py. If you are not using images, another place to look is in text caching. text layout is expensive (to support arbitrary rotations, etc). So I cache the layout information in a dictionary "cached" in the text module. When you change the xlim/ylim, that would trigger a new layout and an addition to the cache. We need to add some auto-clearing mechanisms to prevent the cache from growing w/o bound but its not done yet. I find it hard to believe, though, that this would leak 100kb/sec. Assuming a 20Hz frame rate, the leak is about 5kb/sec, and I don't think I'm caching that much info. You can estimate the memory effect of the cached simply by commenting out the line self.cached[key] = ret in the matplotlib.text module. What backend are you using? Are you refreshing the same figure data, or creating new figures? More information would certainly help..... Joe> however I lost some critical functionality in my charts Joe> (which behave like the Windows Task Manager resource monitor Joe> graphs). So I really need this fixed. I will send shortly a Joe> test case which replicates the problem. That would be great. Joe> Since the maintainer is out on vacation, I was also wondering Joe> if anyone knew enough about the internals of matplotlib that Joe> they could give me an idea of which modules (Python or Joe> otherwise) are affected by Axes::set_xlim and Axes::set_ylim. I'm back. I was in Rio for a couple of weeks and have suffered a 95 degree temperature drop returning to Chicago (sigh)... JDH |
From: Joe <gar...@us...> - 2005-01-20 00:10:15
|
Thanks John, Sheesh, 95 degrees, I can't imagine how I'd take that. Some Christmases my family would go visit relatives in Chicago. It seemed just a little bit more warmer (but not that much) when we returned to Oklahoma. Never really gone anywhere to warm for Christmas. More below... On Tuesday 18 January 2005 20:25, John Hunter wrote: > >>>>> "Joe" == Joe <gar...@us...> writes: > > Joe> Hello devels, I chose to use matplotlib for a restaurant > Joe> simulation. It supplied all the features I needed and I was > Joe> pleasantly surprised. However the people I was doing this > Joe> project for mentioned that the simulation slowed down to a > Joe> crawl 10 or so minutes into the simulation. It sounded like > Joe> a memory leak to me so I investigated and found a 100 KB/sec > Joe> leak in Windows (via the interpreter as well as frozen with > Joe> py2exe) as well as in Linux. I narrowed it down to a part of > Joe> the code where I updated xlim and ylim via Axes::set_xlim, > Joe> Axes::set_ylim. Commenting that part out yielded no leak, > > So you're doing animation right? Are you using images, eg imshow? I > just fixed a memory leak in image resizing that amounts to about > 200K/resize -- the changes are in CVS. Of course on windows it's hard > to test because the changes are in extension code, and require > building on win32. The instructions for building on win32 are in the > file setupext.py. I wish so, but no, I'm not using any images. > If you are not using images, another place to look is in text caching. > text layout is expensive (to support arbitrary rotations, etc). So I > cache the layout information in a dictionary "cached" in the text > module. When you change the xlim/ylim, that would trigger a new > layout and an addition to the cache. We need to add some > auto-clearing mechanisms to prevent the cache from growing w/o bound > but its not done yet. I find it hard to believe, though, that this > would leak 100kb/sec. Assuming a 20Hz frame rate, the leak is about > 5kb/sec, and I don't think I'm caching that much info. I am using 5 GTKAgg FIgure widgets with 2-3 subplots a piece (a maximum of 3 subplots get drawn at a time). The simulation runs at 1 Hz. Therefore 6.67 kB/sec at max. Which sounds about right. I am updating each Axes point set when I do the update. > You can estimate the memory effect of the cached simply by commenting > out the line > > self.cached[key] = ret > > in the matplotlib.text module. I'll definitely check that out. With the above math that just might prove to be the culprit. > What backend are you using? Are you refreshing the same figure data, > or creating new figures? More information would certainly help..... > > Joe> however I lost some critical functionality in my charts > Joe> (which behave like the Windows Task Manager resource monitor > Joe> graphs). So I really need this fixed. I will send shortly a > Joe> test case which replicates the problem. > > That would be great. > > Joe> Since the maintainer is out on vacation, I was also wondering > Joe> if anyone knew enough about the internals of matplotlib that > Joe> they could give me an idea of which modules (Python or > Joe> otherwise) are affected by Axes::set_xlim and Axes::set_ylim. > > I'm back. I was in Rio for a couple of weeks and have suffered a 95 > degree temperature drop returning to Chicago (sigh)... > > JDH I'll get the test case up on the web ASAP, I just wanted to reply now to let everyone know that I'm still working on the problem. Joe |
From: Ted D. <ted...@jp...> - 2005-07-22 20:41:55
|
The legend() docs state: Make a legend with existing lines >>> legend() legend by itself will try and build a legend using the label property of the lines/patches/collections. You can set the label of a line by doing plot(x, y, label='my data') or line.set_label('my data'). If label is set to '_nolegend_', the item will not be shown in legend. But trying to pass '_nolegend_' doesn't seem to work. And a grep through the code finds no instances of '_nolegend_'. import pylab as p x = p.arange( 0,3, .1 ) y1 = p.cos( x ) y2 = p.sin( x ) y3 = 2*p.sin( x ) p.plot( x, y1 ) p.plot( x, y2 ) p.plot( x, y3 ) p.legend( ( "cos(x)", "_nolegend_", "2*sin(x)" ) ) p.show() |
From: John H. <jdh...@ac...> - 2005-07-25 14:29:23
|
>>>>> "Ted" == Ted Drain <ted...@jp...> writes: Ted> The legend() docs state: Make a legend with existing lines >>>> legend() Ted> legend by itself will try and build a legend using the Ted> label property of the lines/patches/collections. You can set Ted> the label of a line by doing plot(x, y, label='my data') or Ted> line.set_label('my data'). If label is set to '_nolegend_', Ted> the item will not be shown in legend. The docs say this only in reference to autolegend capability (eg when you call legend with no arguments). And this does work import pylab as p x = p.arange( 0,3, .1 ) p.plot( x, p.cos(x), label='cos(x)' ) p.plot( x, p.sin(x), label='sin(x)') p.plot( x, 2*p.sin(x), label='_nolegend_' ) p.legend() p.show() It isn't really required in your use case, because you can simply pass the lines and labels you want in the legend import pylab as p x = p.arange( 0,3, .1 ) l0, = p.plot( x, p.cos(x)) l1, = p.plot( x, p.sin(x)) l2, = p.plot( x, 2*p.sin(x)) p.legend((l0, l1), ('cos(x)', 'sin(x)') ) p.show() It would not be too much work to support the semi-auto legending of your example p.legend( ( "cos(x)", "_nolegend_", "2*sin(x)" ) ) if you think this is sufficiently useful. JDH |