Hello, I'm running a guarded app. Memory is not released on logout. I read carefully nevow.guard and I'm debugging widely with pdb and gc. I encountered the following problem. It sounds really strange. I discovered, using pdb and gc inside logoutPortal(), that visited pages remain alive. So, I created a WastingMemPage(rand.Page) class that, on __init__, allocates ton of mem (no external referrer, memroy is allocate inside the instance only). I will return it initializing each time: def locateChild(self, ctx, segs): return WastingMemPage(), segs Now, each time I hit one of this WastingMemPage, memory usage grows. When I logout ( portalLogout() ), memory is not released. Now: * Is a rend.Page() not deleted once rendered? * Altough the previous question, why pages remain linked from something after portalLogout()? What's happening? Am I making some mistake? Is there some limit on portalLogout()? py 2.5/2.4. Nevow 0.9.31. Please, help! -- efphe Today is Pungenday, the 62nd day of Confusion in the YOLD 3175
On Mon, Jul 27, 2009 at 7:36 PM, Federico Tomassini <federicotom@yahoo.it>wrote:
I encountered the following problem. It sounds really strange. I discovered, using pdb and gc inside logoutPortal(), that visited pages remain alive.
That does seem pretty strange.
So, I created a WastingMemPage(rand.Page) class Rather than wasting lots of memory to debug, why not use gc.get_referrers to discover what's keeping your rend.Page instance alive? Perhaps it's an object in your own application that you can get rid of. Or, if it's a bug in Nevow, it will tell us where in Nevow. * Is a rend.Page() not deleted once rendered? It certainly *should* be, assuming nothing's hanging on to it...
* Altough the previous question, why pages remain linked from something after portalLogout()?
I don't know. What's happening? Am I making some mistake? Without access to your code — and, I would imagine, a pretty extensive debug log — I couldn't tell you exactly what's happening. Can you construct a minimal example which demonstrates the problem, which someone on this list could run and debug?
Is there some limit on portalLogout()?
No. The behavior you're noticing sounds like a definite bug somewhere; if not in your code then in Nevow itself. py 2.5/2.4. Nevow 0.9.31.
Have you tried Nevow trunk@HEAD? Does the problem still exist?
Dear Glyph, see answers below. I'm debugging with pdb and gc. Maybe I discovered something, but the debug process is slow. Glyph Lefkowitz wrote:
So, I created a WastingMemPage(rand.Page) class
Rather than wasting lots of memory to debug, why not use gc.get_referrers to discover what's keeping your rend.Page instance alive? Perhaps it's an object in your own application that you can get rid of. Or, if it's a bug in Nevow, it will tell us where in Nevow.
Ok. on Page.afterRender() I put `self` on a list. After 5 hits to this page, I'm checking where these pages are referred. I have this for the first page on the list: WovenContext(tag=None, remembrances={'nevow.inevow.IMacroFactory': <myfile.pages.MyPage object at 0x4069eeac>}) Do this tell you something?
Without access to your code — and, I would imagine, a pretty extensive debug log — I couldn't tell you exactly what's happening.
Can you construct a minimal example which demonstrates the problem, which someone on this list could run and debug?
Yes. I will build a minimal framework. -- efphe Today is Prickle-Prickle, the 63rd day of Confusion in the YOLD 3175
Federico Tomassini wrote:
Dear Glyph,
see answers below. I'm debugging with pdb and gc. Maybe I discovered something, but the debug process is slow.
Glyph Lefkowitz wrote:
So, I created a WastingMemPage(rand.Page) class
Rather than wasting lots of memory to debug, why not use gc.get_referrers to discover what's keeping your rend.Page instance alive? Perhaps it's an object in your own application that you can get rid of. Or, if it's a bug in Nevow, it will tell us where in Nevow.
Ok. on Page.afterRender() I put `self` on a list. After 5 hits to this page, I'm checking where these pages are referred. I have this for the first page on the list:
WovenContext(tag=None, remembrances={'nevow.inevow.IMacroFactory': <myfile.pages.MyPage object at 0x4069eeac>})
Do this tell you something?
Without access to your code — and, I would imagine, a pretty extensive debug log — I couldn't tell you exactly what's happening.
Can you construct a minimal example which demonstrates the problem, which someone on this list could run and debug?
Yes. I will build a minimal framework.
Hello, I coded a minimal example. Problem seems to depend from Bar.data_somedata(). If I remove the interested tag from the docFactory, memory is released. When, instead, I use this tag (and Bar.data_somedata()), memory is not released: http://dpaste.com/72343/ -- efphe Today is Prickle-Prickle, the 63rd day of Confusion in the YOLD 3175
Federico Tomassini wrote:
Hello,
I coded a minimal example. Problem seems to depend from Bar.data_somedata(). If I remove the interested tag from the docFactory, memory is released. When, instead, I use this tag (and Bar.data_somedata()), memory is not released:
Ok, this minimal server application proofs that a memory leak exists somewhere. This is already a good result. Remember i'm not an expert: I spent many hours to write this little snippet of code. I spent other hours to isolate the problem and I have another result. If we put, on afterRender(), the following: def afterRender(self, *a): self.docFactory._cache[1].parent.parent= None the memory leak desappears (at least the greater). This proofs, I think, that context hier has to be cleaned somehow. Probably it would be safer to do: def afterRender(self, *a): self.docFactory._cache[1].parent.parent= None self.docFactory._cache[1].parent= None and maybe: def afterRender(self, *a): self.docFactory._cache[1].parent.parent= None self.docFactory._cache[1].parent= None self.docFactory._cacche= None But this is not a bugfix, This is a proof of blackhole existence. Is there someone able to locate his origin? -- efphe Today is Prickle-Prickle, the 63rd day of Confusion in the YOLD 3175
On Tue, 28 Jul 2009 18:45:04 +0200, Federico Tomassini <federicotom@yahoo.it> wrote:
Federico Tomassini wrote:
Hello,
I coded a minimal example. Problem seems to depend from Bar.data_somedata(). If I remove the interested tag from the docFactory, memory is released. When, instead, I use this tag (and Bar.data_somedata()), memory is not released:
Ok, this minimal server application proofs that a memory leak exists somewhere. This is already a good result.
I messed around with this for a while. Unfortunately, I am not able to reproduce a memory leak using it. I found some things which I find suspicious in Nevow, but none of them explains a leak. Sorry. Jean-Paul
On Wed, Jul 29, 2009 at 5:17 PM, Jean-Paul Calderone <exarkun@divmod.com>wrote:
On Tue, 28 Jul 2009 18:45:04 +0200, Federico Tomassini < federicotom@yahoo.it> wrote:
Federico Tomassini wrote:
Ok, this minimal server application proofs that a memory leak exists somewhere. This is already a good result.
I messed around with this for a while. Unfortunately, I am not able to reproduce a memory leak using it. I found some things which I find suspicious in Nevow, but none of them explains a leak.
Just for posterity, did you try it with the latest release, or just with trunk? (This question is both for Frederico and Jean-Paul.)
On Wed, 29 Jul 2009 17:51:53 -0400, Glyph Lefkowitz <glyph@twistedmatrix.com> wrote:
On Wed, Jul 29, 2009 at 5:17 PM, Jean-Paul Calderone <exarkun@divmod.com>wrote:
On Tue, 28 Jul 2009 18:45:04 +0200, Federico Tomassini < federicotom@yahoo.it> wrote:
Federico Tomassini wrote:
Ok, this minimal server application proofs that a memory leak exists somewhere. This is already a good result.
I messed around with this for a while. Unfortunately, I am not able to reproduce a memory leak using it. I found some things which I find suspicious in Nevow, but none of them explains a leak.
Just for posterity, did you try it with the latest release, or just with trunk?
Python 2.5, trunk of Twisted, trunk of Nevow. Jean-Paul
Jean-Paul Calderone wrote:
Ok, this minimal server application proofs that a memory leak exists somewhere. This is already a good result.
I messed around with this for a while. Unfortunately, I am not able to reproduce a memory leak using it. I found some things which I find suspicious in Nevow, but none of them explains a leak.
Are you saying that you are not sure about memory leaks existence? The previous example allocates memory such way: def afterRender(self, *a): self.foo= ['a' * (10**6) for i in xrange(100)] When logout, memory remains allocated unless you create a destroyer method that deletes the foo attr before the exit, explicitley. Memory leaks appears also when rend.Page.data_bar() is used. Both cases seem to be related to WovenContext and docFactory (a lot of WovenCtx and IMacroFactory instances seems to stick in docFactory._cache). In fact, this part of nevow is simply a Memory Blackhole. Inside docFactory._cache one can find various sticky objects. So, why "you are not able to reproduce it"? This is a *really heavy* problem. So, imho, nevow should work on it with energies. Maybe the better way is to redesign WovenCtx machinery, as Jean-Paul suggested. But it's absolutely important to make an intervention. I can help. If we need to redesign WovenCtx and someone is able to guide my work (requiring to me precise APIs or Classes), you can rely on my contribution. Br -- efphe Today is Setting Orange, the 64th day of Confusion in the YOLD 3175
On Thu, 30 Jul 2009 01:34:26 +0200, Federico Tomassini <federicotom@yahoo.it> wrote:
Jean-Paul Calderone wrote:
Ok, this minimal server application proofs that a memory leak exists somewhere. This is already a good result.
I messed around with this for a while. Unfortunately, I am not able to reproduce a memory leak using it. I found some things which I find suspicious in Nevow, but none of them explains a leak.
Are you saying that you are not sure about memory leaks existence?
No, only that I am not able to reproduce it (I believe you when you say that you have a server which leaks memory).
The previous example allocates memory such way:
def afterRender(self, *a): self.foo= ['a' * (10**6) for i in xrange(100)]
When logout, memory remains allocated unless you create a destroyer method that deletes the foo attr before the exit, explicitley.
Memory leaks appears also when rend.Page.data_bar() is used. Both cases seem to be related to WovenContext and docFactory (a lot of WovenCtx and IMacroFactory instances seems to stick in docFactory._cache).
Yes, this I am able to observe. However, this leak limits itself to a single instance. After the first request, no further memory is leaked (when I try the example you provided).
In fact, this part of nevow is simply a Memory Blackhole. Inside docFactory._cache one can find various sticky objects.
Yes, but they're generally things which are needed over and over again for every request. That is the purpose of the cache. :)
So, why "you are not able to reproduce it"?
When I run the example, it starts off by using about 10MB of memory. When I make one request of it, it jumps to 50MB of memory. When I make a second (or third, or any additional number) request of it, memory usage remains at 50MB. So, that's what I mean.
This is a *really heavy* problem. So, imho, nevow should work on it with energies.
I can understand how it would seem to be a very serious problem from your perspective. It probably makes your Nevow-based application unusable, or at least require significant additional administrative resources. However... none of *my* Nevow-based applications exhibit this behavior. Even ignoring the fact that this makes it very difficult for me to try to fix the problem (or even understand what the problem is - I still don't, by the way), this means it's not going to work its way very far up my list of priorities - sorry. There are other ways to move things up my list of priorities, most prominently, you could fund the debugging and development required to fix the issue. As my employer has recently become defunct, the logistics of this are slightly complicated, but I'm sure we can work something out if you are interested. All that said, I'm still happy to give you my time in working on this, provided an example I can use to reproduce the misbehavior myself. Without this, it's just too hard.
Maybe the better way is to redesign WovenCtx machinery, as Jean-Paul suggested. But it's absolutely important to make an intervention.
I can help. If we need to redesign WovenCtx and someone is able to guide my work (requiring to me precise APIs or Classes), you can rely on my contribution.
Some effort has been directed towards this goal already. Element supersedes Fragment. It comes with a flattener which doesn't use the context (except for backwards compatibility). The next step is to provide a similar class to supersede Page. This hasn't been extremely high priority, since it's always possible to structure all of your rendering logic as a number of Elements with only the thinnest layer of support from Page. Jean-Paul
On Wed, Jul 29, 2009 at 7:34 PM, Federico Tomassini <federicotom@yahoo.it>wrote:
I can help.
The first thing you can do to help is to try with Nevow trunk :-). You said in your first email that it was from 0.9.31. exarkun has not tried with 0.9.31. 0.9.31 was released over a year ago. There are many bugs which have been fixed since then; we may already have addressed whatever is causing your problem. Have you done that yet? Were the results the same?
Glyph Lefkowitz wrote:
On Wed, Jul 29, 2009 at 7:34 PM, Federico Tomassini <federicotom@yahoo.it <mailto:federicotom@yahoo.it>> wrote:
I can help.
The first thing you can do to help is to try with Nevow trunk :-). You said in your first email that it was from 0.9.31. exarkun has not tried with 0.9.31. 0.9.31 was released over a year ago. There are many bugs which have been fixed since then; we may already have addressed whatever is causing your problem.
Have you done that yet? Were the results the same?
Ok, I'll do it. Stay tuned. -- efphe Today is Setting Orange, the 64th day of Confusion in the YOLD 3175
participants (3)
-
Federico Tomassini
-
Glyph Lefkowitz
-
Jean-Paul Calderone