|
-
Loader - memory problem
Hi. I use a loader to import an image into flash.
Code:
private var _loader:Loader = new Loader();
I add a listener and start loading.
Code:
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete);
_loader.load(new URLRequest("bilder/" + e.sökväg + "STOR.jpg"));
When it's complete I remove the listener
Code:
e.target.removeEventListener(Event.COMPLETE, loaderComplete);
And I do absolutely nothing with the loaded image, I don't add it to
the display list or anything. But when I use the unload() method on the loader it doesn't disappear from memory! Even if I set the _loader = null it doesn't free up the memory!
What the f*** is wrong? Any help would be deeply appreciated!
I check the System.totalMemory property and it just keeps stacking up if I repeat the process.
Last edited by TwinPeaksBob; 05-06-2009 at 01:51 PM.
-
Unload just clears the reference between the loader and the data - you still need to wait for 2-3 passes of the garbage collector before the memory is reclaimed.
-
Senior Member
It will probably be swept on the next pass, but I always do this to speed it up and make sure...
if (loader.content && loader.content.bitmapData) {
loader.content.bitmapData.dispose();
}
unload();
That clears the bitmap's pixels and reduces its size to 0x0 immediately. Useful if you're running a ton of loaded bitmaps and need to clear 'em fast...
-
newb of many sorts
If you have the debug version of flash installed, you can force garbage collection with System.gc()
It doesn't work for the standard flash player, but it will atleast help you to be sure that your images are indead being collected.
I haven't tried joshstrike's method, it sounds like a good solution though.
Search first, asked questions later.
-
Senior Member
Golly, that's cool!
For years I've been making LocalConnections to force the GC into action...it works for some unknown reason. But that's nice!
-
 Originally Posted by joshstrike
It will probably be swept on the next pass, but I always do this to speed it up and make sure...
if (loader.content && loader.content.bitmapData) {
loader.content.bitmapData.dispose();
}
unload();
That clears the bitmap's pixels and reduces its size to 0x0 immediately. Useful if you're running a ton of loaded bitmaps and need to clear 'em fast...
Alright, thanks!
-
I'm still not getting it to work though, gah this is driving me insane! Please help!
I've created this code to try it out, but totalMemory just keeps stacking up!
stage.addEventListener(Event.ENTER_FRAME, kolla);
stage.addEventListener(MouseEvent.CLICK, add);
stage.addEventListener(KeyboardEvent.KEY_DOWN, reportKeyDown);
var objekt:Loader;
var bildArray:Array = new Array();
var bildIndex:uint = new uint();
function kolla(e:Event):void
{
trace(System.totalMemory);
}
function add(e:MouseEvent):void
{
objekt = new Loader();
bildArray[bildIndex] = objekt;
//objekt.contentLoaderInfo.addEventListener(Event.CO MPLETE, loadComplete);
objekt.load(new URLRequest("DubaiSTOR.jpg"));
bildIndex++;
}
function reportKeyDown(e:KeyboardEvent):void
{
if (bildIndex > 0) {
bildArray[bildIndex - 1].content.bitmapData.dispose();
bildArray[bildIndex - 1].unload();
bildArray[bildIndex - 1] = null;
bildIndex--;
}
trace(System.totalMemory + "SCHANSE");
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}
}
Last edited by TwinPeaksBob; 05-07-2009 at 10:49 AM.
-
Senior Member
GC is funny. It doesn't happen in the IDE like it does in a browser. You're never going to see it operate properly by tracing out totalMemory. You need to monitor usage from within a browser, over time, and note too that it isn't immediate.
I use a great tool called ActiveGraph for finding as3 memory leaks while testing in a browser. It isn't available at the author's site anymore so I'm going to post the whole class here. See if this helps.
just include it, instantiate it, and add it to the stage.
Code:
/**
* ActiveGraph 1.4: an overthought shot in the dark
* by Jeremy Sachs June 2, 2007
*
* I have no blog, yet. When I have one, visit it.
* Maybe by then I'll have a new ActiveGraph.
*
* You may distribute this class freely, provided it is not modified in any way (including
* removing this header or changing the package path).
*
* [email protected]
*/
/* parameters of ActiveGraph (all are optional):
* interval- the length of time (in milliseconds) between memory checks.
* (NOTE: a memory check does not always make a point on the graph, only when there's relevant data.)
* verbose- when set to true, this traces data to your Output menu.
* visible- when set to false, this keeps Activegraph from drawing to the screen.
* degree- sets the number of sawtooth patterns to compensate for. (Default is 2)
*/
package Active
{
// import statements
import flash.display.Sprite;
import flash.display.Shape;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.system.System;
/**
* ActiveGraph class
* Graphs and displays or outputs memory usage,
* measured in pages- 4-kilobyte chunks
*/
public class ActiveGraph extends Sprite
{
private const WIDTH:Number = 50, HEIGHT:Number = 15;
private const MEGABYTES:Number = 1/1048576, PAGE:Number = 4096;
private var verboseMode:Boolean, returnVal:Boolean;
private var lastPlot1:int, lastPlot2:int, plot:int, plotLength:int;
private var high:Number, low:Number, itr:Number;
private var history:Array;
private var output:String, sign:String;
private var timer:Timer;
// display-related properties
private var textBox:TextField;
private var textFormat:TextFormat;
private var graphBackground:Sprite;
private var plotLine:Shape;
private var backX:Number, backY:Number;
private var numerator:Number, denominator:Number, average:int, old:int;
private var caught2:Boolean = false;
private var fn:Function;
public function ActiveGraph(interval:Number=0, verbose:Boolean=false, drawData:Boolean=true, degree:int=2):void
{
degree = Math.min(degree, 2);
lastPlot1 = lastPlot2 = plot = plotLength = 0;
history = new Array();
numerator = denominator = average = 0;
timer = new Timer(interval);
verboseMode = verbose;
switch (degree) {
case 0 :
fn = test0;
break;
case 2 :
fn = test2;
break;
default :
fn = test1;
break;
}
if (drawData) {
// instantiate drawing objects
textBox = new TextField();
textFormat = new TextFormat();
graphBackground = new Sprite();
plotLine = new Shape();
// format textBox
textFormat.size = 9;
textFormat.font = "Monaco";
textFormat.color = 0xFFFFFF;
textBox.selectable = false;
textBox.autoSize = TextFieldAutoSize.LEFT;
textBox.x = WIDTH + 5;
textBox.height = HEIGHT;
// draw graphBackground
graphBackground.graphics.beginFill(0);
graphBackground.graphics.drawRect(0,0,WIDTH + 85,HEIGHT);
graphBackground.graphics.endFill();
graphBackground.graphics.lineStyle(0.5,0xFFFFFF);
graphBackground.graphics.drawRect(0,0,WIDTH,HEIGHT-1);
// add to display list
this.addChild(graphBackground);
this.addChild(plotLine);
this.addChild(textBox);
timer.addEventListener(TimerEvent.TIMER, drawMem, false, 0, true);
// implements clicking and dragging behavior
textBox.mouseEnabled = false;
backX = x, backY = y;
graphBackground.addEventListener(MouseEvent.MOUSE_DOWN, handleDrag, false, 0, true);
graphBackground.addEventListener(MouseEvent.MOUSE_UP, handleDrag, false, 0, true);
this.addEventListener(Event.ADDED_TO_STAGE, loadDrag, false, 0, true);
} else {
trace("ActiveGraph Running.");
timer.addEventListener(TimerEvent.TIMER, trackMem, false, 0, true);
}
timer.start();
}
// trackMem- determines whether the GC has run, outputs active memory
private function trackMem(e:TimerEvent = null):Boolean
{
returnVal = false;
plot = System.totalMemory/PAGE;
old = average;
numerator += plot;
denominator++;
average = numerator/denominator;
// if the plot is relevant...
if (fn() && verboseMode) {
trace(plot);
}
return returnVal;
}
// test0: doesn't clean up sawteeth
private function test0():Boolean
{
if (lastPlot1 != plot) {
returnVal = true;
lastPlot1 = plot;
}
return returnVal;
}
// test1: cleans up DRC sawteeth
private function test1():Boolean
{
returnVal = (!lastPlot1 || lastPlot1 > plot);
lastPlot1 = plot;
return returnVal;
}
// test2: cleans up mark'n'sweep sawteeth
private function test2():Boolean
{
if (lastPlot1 > plot || !lastPlot1) {
if (lastPlot2 > plot || !lastPlot2) {
caught2 = true;
}
lastPlot2 = plot;
} else if (lastPlot1 < plot && caught2) {
plot = lastPlot2;
returnVal = true;
caught2 = false;
}
lastPlot1 = plot;
return returnVal;
}
// drawMem- updates graph and textbox
private function drawMem(e:TimerEvent = null):void
{
if (trackMem()) {
plotLine.graphics.clear();
// history array never exceeds a certain length
if (plotLength == 21) {
history.shift();
plotLength--;
}
// determines whether to display +/- for memory increase/decrease
if (plot > history[int(plotLength-1)]) {
sign = "+ , ";
} else if (plot < history[int(plotLength-1)]) {
sign = "- , ";
} else {
sign = " , ";
}
// add plot to data set
history.push(plot);
plotLength = history.length;
// If the graph's long enough,
if (plotLength > 1) {
plotLine.graphics.lineStyle(2.5,0xFF0000);
high = 0, low = Infinity;
// find the top and bottom extrema,
for (itr = 0; itr < plotLength; itr++) {
high = Math.max(history[itr], high);
low = Math.min(history[itr], low);
}
// then plot the graph.
plotLine.graphics.moveTo(0, HEIGHT*(1-(history[0]-low)/(high-low)));
for (itr = 1; itr < plotLength; itr++) {
// I hate the math. I hate writing it out.
plotLine.graphics.lineTo(WIDTH*itr/(plotLength-1),
HEIGHT*(1-(history[itr]-low)/(high-low)));
}
}
// put output text in textBox
output = plot+sign;
textBox.text = String(output)+String(average);
textBox.setTextFormat(textFormat);
}
}
private function handleDrag(e:Event):void
{
// based on the event type,
switch (e.type) {
case MouseEvent.MOUSE_DOWN :
// start dragging,
backX = x, backY = y;
startDrag();
break;
case MouseEvent.MOUSE_UP :
// stop dragging,
stopDrag();
break;
case Event.MOUSE_LEAVE :
// or reset the positiong, in case it's been dragged off the Stage
stopDrag();
x = backX, y = backY;
break;
}
}
private function loadDrag(e:Event):void
{
this.stage.addEventListener(Event.MOUSE_LEAVE, handleDrag, false, 0, true);
}
public function get data():Number
{
return plot;
}
}
}
-
 Originally Posted by joshstrike
Hey dude thanks! You were right, System.totalMemory can't be trusted 
I used ActiveGraph as well as the Activity Control and saw that the memory actually gets freed!
So thanks
-
Senior Member
Is the graph only a small box in the upper left hand corner of the swf....doesn't seem like much of a graph to me.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|