You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@flex.apache.org by Nigel Magnay <ni...@gmail.com> on 2013/09/19 17:31:03 UTC

Memory Leaking through LayoutManager

Hello.

In our code, someone has implemented a custom spark text area, that
attempts to resize based on the number of lines in the text.

Snippet-ish:

<s:TextArea updateComplete="updateCompleteHandler(event)" ... >

...

private function updateCompleteHandler(event:FlexEvent):void {


textFlow.flowComposer.composeToPosition();

var actualNumOfLines: int = textFlow.flowComposer.numLines;

heightInLines = actualNumOfLines;

}


This is then used in a form on a popup. It all works as desired. However,
in trying to track down an enormous memory leak, I think this component
with LayoutManager is responsible.

It seems that if this handler is called - but the component is not on the
screen (it's on the bottom of the popup form, hidden by a scrollbar), then
things go wrong. The

heightInLines = <value>

calls invalidateProperties, which causes the global LayoutManager to add
the component into several priorityqueues. When the dialog is finished,
and I haven't made the control visible (by scrolling) at any point, the
control is still in that priorityqueue (the invalidatePropertiesQueue),
nothing gets released, boom - massive memory leak (which additionally does
not seem to show up in the flex profiler).

Is this a bug? Are there some other rules around cleaning up the layout
manager, or not calling invalidate functions ? Whilst I can work around
this issue in this instance, I'm slightly concerned there are other
instances of controls that are never added which might exhibit the same
behaviour...

Re: Memory Leaking through LayoutManager

Posted by Nigel Magnay <ni...@gmail.com>.
Yes - you were right, there was a loop whereby effectively the
updateComplete handler was re-adding the component into the 'to be updated'
list. Once we found that, it was relatively easy to fix the leak.




On Thu, Sep 19, 2013 at 5:21 PM, Alex Harui <ah...@adobe.com> wrote:

> There's a difference between being "not visible" and "not being on the
> display list".
> AFAIK, you can be hidden by scrollbars, masks, and just about anything
> else, but if you are on the display list (which doesn't mean on stage
> either, just that there is a chain of parenting going back up to the
> Application), then the LayoutManager will validate you and remove you from
> its queues.
>
> I think you can be on the display list, call invalidation to get in the
> queue and get removed from the display list before validation and that
> might get you stuck in the queue.
>
> The profiler should show that object.  Make sure you've turned off all
> filters.
>
> It is also possible that the code you showed results in a "layout loop"
> where the object is constantly being re-added to one of the queues.  If an
> updateComplete handler results in a call to an invalidateXXX method, then
> you get re-added to the queue and updateComplete gets called eventually
> which, if it results in a call to an invalidateXXX method, you have a
> "layout loop".
>
> HTH,
> -Alex
>
> On 9/19/13 8:31 AM, "Nigel Magnay" <ni...@gmail.com> wrote:
>
> >Hello.
> >
> >In our code, someone has implemented a custom spark text area, that
> >attempts to resize based on the number of lines in the text.
> >
> >Snippet-ish:
> >
> ><s:TextArea updateComplete="updateCompleteHandler(event)" ... >
> >
> >...
> >
> >private function updateCompleteHandler(event:FlexEvent):void {
> >
> >
> >textFlow.flowComposer.composeToPosition();
> >
> >var actualNumOfLines: int = textFlow.flowComposer.numLines;
> >
> >heightInLines = actualNumOfLines;
> >
> >}
> >
> >
> >This is then used in a form on a popup. It all works as desired. However,
> >in trying to track down an enormous memory leak, I think this component
> >with LayoutManager is responsible.
> >
> >It seems that if this handler is called - but the component is not on the
> >screen (it's on the bottom of the popup form, hidden by a scrollbar), then
> >things go wrong. The
> >
> >heightInLines = <value>
> >
> >calls invalidateProperties, which causes the global LayoutManager to add
> >the component into several priorityqueues. When the dialog is finished,
> >and I haven't made the control visible (by scrolling) at any point, the
> >control is still in that priorityqueue (the invalidatePropertiesQueue),
> >nothing gets released, boom - massive memory leak (which additionally does
> >not seem to show up in the flex profiler).
> >
> >Is this a bug? Are there some other rules around cleaning up the layout
> >manager, or not calling invalidate functions ? Whilst I can work around
> >this issue in this instance, I'm slightly concerned there are other
> >instances of controls that are never added which might exhibit the same
> >behaviour...
>
>

Re: Memory Leaking through LayoutManager

Posted by Alex Harui <ah...@adobe.com>.
There's a difference between being "not visible" and "not being on the
display list".
AFAIK, you can be hidden by scrollbars, masks, and just about anything
else, but if you are on the display list (which doesn't mean on stage
either, just that there is a chain of parenting going back up to the
Application), then the LayoutManager will validate you and remove you from
its queues.

I think you can be on the display list, call invalidation to get in the
queue and get removed from the display list before validation and that
might get you stuck in the queue.

The profiler should show that object.  Make sure you've turned off all
filters.

It is also possible that the code you showed results in a "layout loop"
where the object is constantly being re-added to one of the queues.  If an
updateComplete handler results in a call to an invalidateXXX method, then
you get re-added to the queue and updateComplete gets called eventually
which, if it results in a call to an invalidateXXX method, you have a
"layout loop".

HTH,
-Alex

On 9/19/13 8:31 AM, "Nigel Magnay" <ni...@gmail.com> wrote:

>Hello.
>
>In our code, someone has implemented a custom spark text area, that
>attempts to resize based on the number of lines in the text.
>
>Snippet-ish:
>
><s:TextArea updateComplete="updateCompleteHandler(event)" ... >
>
>...
>
>private function updateCompleteHandler(event:FlexEvent):void {
>
>
>textFlow.flowComposer.composeToPosition();
>
>var actualNumOfLines: int = textFlow.flowComposer.numLines;
>
>heightInLines = actualNumOfLines;
>
>}
>
>
>This is then used in a form on a popup. It all works as desired. However,
>in trying to track down an enormous memory leak, I think this component
>with LayoutManager is responsible.
>
>It seems that if this handler is called - but the component is not on the
>screen (it's on the bottom of the popup form, hidden by a scrollbar), then
>things go wrong. The
>
>heightInLines = <value>
>
>calls invalidateProperties, which causes the global LayoutManager to add
>the component into several priorityqueues. When the dialog is finished,
>and I haven't made the control visible (by scrolling) at any point, the
>control is still in that priorityqueue (the invalidatePropertiesQueue),
>nothing gets released, boom - massive memory leak (which additionally does
>not seem to show up in the flex profiler).
>
>Is this a bug? Are there some other rules around cleaning up the layout
>manager, or not calling invalidate functions ? Whilst I can work around
>this issue in this instance, I'm slightly concerned there are other
>instances of controls that are never added which might exhibit the same
>behaviour...