From pykde Wed Apr 08 21:52:06 2015 From: Andreas Pakulat Date: Wed, 08 Apr 2015 21:52:06 +0000 To: pykde Subject: Re: [PyQt] Debug potential memory leaks Message-Id: X-MARC-Message: https://marc.info/?l=pykde&m=142853003223447 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--===============0485396948064902079==" --===============0485396948064902079== Content-Type: multipart/alternative; boundary=001a113ac482cc332c05133d8a8f --001a113ac482cc332c05133d8a8f Content-Type: text/plain; charset=UTF-8 Hi, On Wed, Apr 8, 2015 at 10:42 AM, Andreas Pakulat wrote: > Hi Phil, > > On Tue, Apr 7, 2015 at 9:55 PM, Phil Thompson > wrote: > >> On 07/04/2015 8:47 pm, Andreas Pakulat wrote: >> >>> Hi, >>> >>> I'm having a small 'systray' application that monitors a jenkins service >>> and it seems there's some kind of memory leak, especially on MacOSX. >>> After >>> having it run for a while (with the machine going to sleep now and again) >>> it starts eating quite some memory - if I understand top/ActivityMonitor >>> correctly - and amd wondering now how I'd best debug a PyQt application's >>> memory consumption. >>> >>> So what tools do you guys usually use to debug such memory leaks? I've >>> tried valgrind on Linux but there's no good hint there, possibly also due >>> to the way Python works. >>> >> >> You could try a debug version of Python that will track objects. If that >> shows objects are not being collected then it is probably a PyQt problem. >> Otherwise it might be more likely to be a Qt problem. > > > I'll check that option if I can determine its not my own code hanging on > to objects it shouldn't hang onto anymore... > So, it seems like I'm leaking QAction's and they're not garbage-collected for quite a while even when they're not connected to anymore anymore. I can 'fix' the problem by setting their parent QObject to None and explicitly calling gc.collect, without the latter the objgraph module ( http://mg.pov.lt/objgraph.py) shows them as objects without any references to them even after another minute of the application running. Maybe a little background on what the app does helps to understand this a little better. It polls a jenkins instance for states of the various jobs and for each job a QAction is created and added to the menu of a QSysTray object. Each time the data is retrieved all existing QActions are removed from teh menu via removeAction and the dictionary that kept the instances is cleared. Then a new set of actions is created and added to the menu for the possibly-changed set of jobs and their changed icons. The parent object of the actions is the systray's menu, hence having to set their parent to None when I want to get rid of them makes sense. What I find surprising though is that Python's gc does not clean them up even after a while unless I explicitly call gc.collect. Does someone have an explanation for this? Andreas --001a113ac482cc332c05133d8a8f Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hi,

On Wed, Apr 8, 2015 at 10:42 AM, Andreas Pakulat <<= a href=3D"mailto:apaku@gmx.de" target=3D"_blank">apaku@gmx.de> wrote:
Hi Phil,

On Tue, Apr 7, 2015 a= t 9:55 PM, Phil Thompson <phil@riverbankcomputing.com> wrote:
On 07/04/2015 8:47 pm, Andreas Pa= kulat wrote:
Hi,

I'm having a small 'systray' application that monitors a jenkin= s service
and it seems there's some kind of memory leak, especially on MacOSX. Af= ter
having it run for a while (with the machine going to sleep now and again) it starts eating quite some memory - if I understand top/ActivityMonitor correctly - and amd wondering now how I'd best debug a PyQt application= 's
memory consumption.

So what tools do you guys usually use to debug such memory leaks? I've<= br> tried valgrind on Linux but there's no good hint there, possibly also d= ue
to the way Python works.

You could try a debug version of Python that will track objects. If that sh= ows objects are not being collected then it is probably a PyQt problem. Oth= erwise it might be more likely to be a Qt problem.

I'll check that option if I can determine its not my own= code hanging on to objects it shouldn't hang onto anymore...

So, it seems like I'm le= aking QAction's and they're not garbage-collected for quite a while= even when they're not connected to anymore anymore. I can 'fix'= ; the problem by setting their parent QObject to None and explicitly callin= g gc.collect, without the latter the objgraph module (http://mg.pov.lt/objgraph.py) shows them as =C2=A0o= bjects without any references to them even after another minute of the appl= ication running.

Maybe a little background on what= the app does helps to understand this a little better. It polls a jenkins = instance for states of the various jobs and for each job a QAction is creat= ed and added to the menu of a QSysTray object. Each time the data is retrie= ved all existing QActions are removed from teh menu via removeAction and th= e dictionary that kept the instances is cleared. Then a new set of actions = is created and added to the menu for the possibly-changed set of jobs and t= heir changed icons. The parent object of the actions is the systray's m= enu, hence having to set their parent to None when I want to get rid of the= m makes sense.

What I find surprising though is th= at Python's gc does not clean them up even after a while unless I expli= citly call gc.collect. Does someone have an explanation for this?

Andreas
--001a113ac482cc332c05133d8a8f-- --===============0485396948064902079== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KUHlRdCBtYWls aW5nIGxpc3QgICAgUHlRdEByaXZlcmJhbmtjb21wdXRpbmcuY29tCmh0dHA6Ly93d3cucml2ZXJi YW5rY29tcHV0aW5nLmNvbS9tYWlsbWFuL2xpc3RpbmZvL3B5cXQ= --===============0485396948064902079==--