Hi Folks,
I've been hunting memory leaks in a large application for my company
(shame on Adobe for not putting in an option for weak references in
ChangeWatchers!) and have noticed something. If you use a binding or
changeWatcher or standard event listener on a popUpWindow, you of course
get a nasty memory leak. However, I'm finding that even if you avoid
such things, popping up and closing a window continuously does in fact
cause a very slight but very real memory leak over time.
Running the following application over ten minutes shows a rise in about
five megs of memory.
Can anyone confirm that they've seen something like this? Is this
something that just has to be lived with, or is there a way to ensure
that standard use of the flex components doesn't cause leaks?
<!-- MyApp.mxml -->
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:local="*"
creationComplete="addObject()"
layout="vertical">
<mx:Script>
<![CDATA[
import mx.containers.TitleWindow;
import mx.managers.PopUpManager;
import flash.utils.setTimeout;
public var popUps:Array = []
public function addObject():void
{
var dialog:TitleWindow = new TitleWindow();
PopUpManager.addPopUp(dialog,this);
popUps.push(dialog);
setTimeout(removeAllObjects,50);
}
public function removeAllObjects():void
{
for each(var item:TitleWindow in popUps){
PopUpManager.removePopUp(item);
}
popUps = [];
setTimeout(addObject,50);
}
]]>
</mx:Script>
<local:MemoryMonitor id="mm" creationComplete="mm.start()"
width="100%" />
</mx:Application>
<!-- MemoryMonitor.mxml -->
<?xml version="1.0" encoding="iso-8859-1"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
private var timer:Timer;
private var maxmem:Number = 0;
private var lasttotal:Number = 0;
private var initYet:Boolean = false;
private var startTime:Number = new Date().getTime();
private var startBytes:Number = System.totalMemory;
[Bindable]
private var seriesArray:ArrayCollection=new ArrayCollection([]);
private var counter:int=0;
public var maxPoints:Number = 100;
private function fullGC():void
{
// unsupported hack that seems to force a full GC
try
{
var lc1:LocalConnection = new LocalConnection();
var lc2:LocalConnection = new LocalConnection();
lc1.connect('name');
lc2.connect('name');
}
catch (e:Error)
{
}
}
private function timerHandler(event:Event):void
{
var totalmem:Number = System.totalMemory;
lasttotal = totalmem;
total.text = totalmem.toString();
maxmem = Math.max(maxmem, System.totalMemory);
max.text = maxmem.toString();
if(counter++%10==0){
fullGC();
setMin();
}
seriesArray.addItem({time:new Date().getTime(),
value:totalmem});
var len:int = seriesArray.length;
if(len>=maxPoints){
var rand:Number = Math.random();
// remove a fairly recent random point
var index:int =
Math.floor((1-rand*rand*rand)*(maxPoints-1));
seriesArray.removeItemAt(index+1);
}
if (callbackFunction != null)
callbackFunction();
}
private function setMin():void
{
var min:Number = -1;
for each(var item:Object in seriesArray){
if(min==-1)
min = item.value;
else if (min>item.value)
min = item.value;
}
LinearAxis(chart.verticalAxis).minimum = min;
}
public var interval:int = 100;
public var callbackFunction:Function = null;
public function start():void
{
timer = new Timer(interval);
timer.addEventListener("timer", timerHandler);
timer.start();
}
public function stop():void
{
timer.stop();
timer.removeEventListener("timer", timerHandler);
timer = null;
}
]]>
</mx:Script>
<mx:HBox>
<mx:Label text="current memory:" />
<mx:Label id="total" text="0" width="100" />
<mx:Spacer width="20" />
<mx:Label text="max memory:" />
<mx:Label id="max" text="0" width="100" />
<mx:Spacer width="20" />
<mx:Button label="resetChart" click="seriesArray.removeAll()" />
</mx:HBox>
<mx:LineChart id="chart" height="100" width="100%" showDataTips="true"
>
<mx:horizontalAxis>
<mx:DateTimeAxis />
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:LinearAxis />
</mx:verticalAxis>
<mx:series>
<mx:LineSeries dataProvider="{seriesArray}" xField="time"
yField="value"/>
</mx:series>
</mx:LineChart>
</mx:VBox>