Can you expect flash/as3 player to eventually garbage collect? - actionscript-3

So I'm quite aware of flash/as3 garbage collecting causing memory leaks, and all the questions on the net.
Our software runs a swf, that loads in other swfs, videos, and images. It is expected to run a week without being restarted. generally, the player barely makes it a week without crashing from using too much memory. the swf will load in other assets based on the time of day, or if the schedule has changed. I wrote a simple resource manager so that it keeps track of what is used and what isn't, and will unload and set the unused assets to null. it does this unused check every hour, but it still seems that memory still doesn't go down after these assets are unloaded, and the memory leak continues to grow.
What I'm wondering, and can't seem to find, is can you expect flash to for SURE eventually release memory that is unused? or is there a possibility that flash may NEVER release unused memory?

It's really hard to find where memory-leaks come from without tools.
During game developpement I use Flash Builder Profiler, allow me to see if all my objects are destroyed when they are supposed to be.
In your case I would take a look at Adobe Scout :
http://gaming.adobe.com/technologies/scout/
Introduction to adobe scout: https://www.youtube.com/watch?v=yUHipsoGB2U
Using those tools during and after game developpement are the way to deal with memory-leaks.

Flash should be garbage collecting things that are no longer referenced. Is it possible that there are still references to whatever you're trying to garbage collect? You'll need to use removeEventListener() anytime that you've used addEventListener() to ensure that all of the references get deleted.
So, if you add an event listener to an object:
foo.addEventListener(Event, functionName)
Then you'll need to remove the reference when you're deleting the object:
foo.removeEventListener(Event, functionName)

It should be garbage collecting. Are you sure you're not inadvertently holding onto a reference to the unused objects? It's pretty easy to forget to remove an event listener, which will prevent an object from being collected when the GC runs.

Related

Loader method unloadAndStop() behaviour

Had some issues using the loader and I feel I need to totally understand how the unloadAndStop() method works. I'm working on a project that loads in multiple swfs when required at runtime. For this I've been using a single loader and pulling out its contents to a cache when it's complete.
The single loader is implemented via an extended class that I haven't written, and it seems to implement the "unloadAndStop(true) method when loading in a new URLRequest.
Now, I've had some strange issues using this system, and I've traced it back to the unloadAndStop(true) call, which according to the Adobe documentation stops audio, playback, and flags for removal by the garbage collector. Obviously this isn't what I want; I still have references to this object on the stage and in my cache! It seems strange to me that there's a way to flag something directly for garbage collection in this manner, where, as far as I know, there's no other way to do that.
So that causes me to assume that in order to properly remove something loaded with a loader you have to unload it in the manner. Is this the case? If I load something in, pull out its contents to movieClip1, load in a new movieClip, and then remove all references to movieClip1 (the original Loader contents) will that be garbage collected, or does it have to be removed via the unloadAndStop method?
TL;DR:
Is it necessary to call unloadAndStop(true) from a loader to guarentee anything it has loaded gets removed from memory, or can the loader load another URLRequest without fear of a memory leak?
It's well described in the docs:
gc:Boolean (default = true) — Provides a hint to the garbage collector to run on the child SWF objects (true) or not (false). If you are unloading many objects asynchronously, setting the gc paramter to false might improve application performance. However, if the parameter is set to false, media and display objects of the child SWF file might persist in memory after running the unloadAndStop() command.
It's because you can have some SWF, get some specific child, and remove the SWF. But you keep reference to it's child, which means that the child won't be garbage collected. But if you force GC to check children, it will try to mark all of them for collection, and leave the ones that are used.
So basically, there is no need to force GC in order to clean things out. The best and most important practice is to remove everything from Stage, and clean all references to it. It will sooner or later going to be checked by GC. unloadAndStop is a shortcut for someone that doesn't keep track on what he's doing and just a safety measure to be sure that you've cleaned as much as you can.
I personally don't use it.

Garbage collecting third-party SWF in AIR

Consider an AIR application which can load any number of third-party SWF files one at a time for display. Like a Web Browser.
The problem is that these SWF files may have EventListeners which have not been removed, etc.
Will Loader.unloadAndStop() be enough to garbage collect these SWFs?
If not- is there an approach which will (maybe a new NativeWindow for each SWF, then close the NativeWindow when done. Will that completely GC?)
Separate native window or loading inside a browser control can be a way for third party SWFs you have no control over. This adds a lot of overhead otherwise.
Unfortunately, you cannot ensure proper sandboxing of the loaded code (the display objects, most importantly, stage cannot be hidden from the loaded code). If the loaded code had added a listener to stage (which is a common thing to do if you need keyboard events), then it will not unload.
This is, however, impossible on mobile devices, where SWF format itself is different.
A while back I had a similar issue with externally developed components to which we didn't have the source, and it was sandwiched into our application. The best I could do / think of, was to do what the nuclear industry does - when things go bad, at least contain it in concrete so it doesn't spread more than it has to.
My solution was to build a 'component pool' so that as the contaminated objects were requested to be "clean" they were put in a separate holding area to be reused when needed - this way only the minimum number needed were ever created during a running session.
You should make a public static function to remove all the listeners in the loaded swf file(s) before you GC it.

AS3: Too Large to Garbage Collect?

I'm working on a flash game that has developed an obvious memory leak. I do what I'm supposed to do with GC; remove all references to the object, nullify it, remove all listeners (or use weak listeners); but the leak is still present.
I've stumbled across this article:
http://www.andymoore.ca/2010/03/motherfucking-as3-garbage-collection/
It claims that objects that are too large will never be garbage collected. This theory fits well with my project since all of my game resides in a couple of huge MovieClips that are created and destroyed often.
Is there any merit to the claim that objects that are too large will never be garbage collected?
I've worked on multiple mid-size to large-size project and the leak you describe seems to be a problem of recursive disposal. You need to really introspect your object from the most nested item and start disposing from that point (stop, nullify, dispose bitmapdata and remove listeners).
I suggest that you take a look at those:
A nice profiler:
https://code.google.com/p/flashpreloadprofiler/
Quasimondo developer on the aviary suite experiencing problem with large bitmap and showing an application that simulate memory assignation:
http://www.quasimondo.com/archives/000691.php
http://www.quasimondo.com/examples/memoryhog.html
Also for more resources on GC issues I suggest you use the Adobe Jira and Bugbase system:
https://bugs.adobe.com/
I do not think there are any merit to that claim. Also read Andy Moore comment:
So doing a quick pass of on-death = null codes, I halved my memory
footprint. I was able to drop that by a further 80% by commenting out
all my “.cacheAsBitmap = true” statements.
You can try using SWFWire Debugger to see exactly which objects aren't being collected.
Disclaimer: This is my own project

Garbage collection - manually wiping EVERYTHING!

I have been building a game for a while (nearly done) - But the game needs a replay button and its a big task.
I know the GC is dreadful in flash, but I wanted to know if there is a way to wipe EVERYTHING as if the flash app has just begun. Clearing memory, game data - I haven't to worry about game loading as its not really heavy on data.
Everything pretty much lives in a DataModel - but I fear if I just clear the all variables, I'll have pockets of orphaned memory.
Any forwarding idea would be great.
cheers guys.
I would do this:
make a class that encapsulates your entire game, called GameContainer or whatever.
Do a search on all your source code, and make sure that in every call to addEventListener, you are passing true for the "use weak references" argument.
In your document class (or frame script), make a single instance of GameContainer and add it to the stage, and do nothing else.
Now when you want to entirely clear your game from memory, remove GameContainer from the stage and null the reference. Memory will not immediately be released, but everything in your game will now be eligible for release. If Flash thinks it needs more memory it will trigger a GC, and the large orphaned GameContainer will be nuked. (Step 2 above will keep your event listeners from counting as references to your objects, and make sure that all self-contained objects are eligible for disposal.
Not sure what you mean about Flash's GC being dreadful though. I can't recall having heard of any bugs in it. It won't nuke your objects unless you are careful with your references, but that's true of all garbage collection.
Not short of refreshing the page. There might be some hack you could do by loading a separate swf and then unloading it, but that would be just as error prone as doing it the proper way.
My advice would be to just buckle down and write your reset function then get something to monitor memory and make sure it works by reiniting/resetting a bunch of times.
The problem with Flash's garbage collector is that as far as I know you cannot FORCE it to "collect". I had this issue with a program in which I would load in various external SWF's, and occasionally Flash would simply not load them. What you may need to do is make a function to set every major variable in your code to null at the end of a game, if you want a true reset.
There is still no guarantee, but unfortunately I'm fairly certain there is no shortcut to force a memory release.
(For me this meant also making sure my event handlers were cleared properly, and my loaders would "unload()" after passing their content off, in the case of my external SWF loader.)

FLVPlayback component memory issues

My website is entirely flash based, it moves around a 3D model which was given to me as chunks of video that I've converted to FLV files. I'm using the FLVPlayback component to control the video inside of my program. While running memory checks using System.totalMemory I've noticed that whenever a video is loaded, it will eat up a chunk of memory and even when I remove all the event listeners from it(they are all weakly referenced), remove the component from its parent, stop the video and null the component instance, it still will not give that memory back.
This has been bothering me since I started working on this project because of the huge amount of video a user can potentially instantiate and load. Currently every video is loaded into a new FLVPlayback instance whenever it is required, but I have read that perhaps the best way to go about this problem is to simply have a global FLVPlayback instance and just reload the new video into the old instance, that way there would only be one FLVPlayback component in the application's memory.
Has anyone else run into this problem as well? Have you found a better solution than using a global instance that you just re-use for every new video?
I've never really liked the components, they're a bit dodgy. This particular problem seems to be common, and the somewhat annoying solution is, as you're suggesting, to only have one FLVPlayback and reuse that.
Here's a blog post about it
You can't help the memory problems much until Flash adds destructors and explicit object deletion, unfortunately. See this thread:
Unloading a ByteArray in Actionscript 3
There's a limit to how much memory Flash applets can use; the GC seems to fire upon reaching that limit. I've seen my memory-easy applets use as much as ~200MB, just because they run for hours on end and the GC doesn't want to kick in.
Oh, and I don't think using a single instance is an elegant solution, either. Currently I just write a dispose() function for my custom classes, waiting for some day when it can be turned into a proper destructor.
From what I gather after a lot of testing is that flash dynamically loads in libraries and components as needed but never garbage collects that data. For instance, if I have a website or an Air app that uses the FLVPlayback component, the actual component and libraries associated with it aren't loaded until a new FLVPlayback() instance is created. It will then load in the library and component into memory but you will never get that space back until the program / website is closed. That specific instance with the video inside of it will get garbage collected and release some memory as long as you remove listeners from it, take it off the stage, and set it to null.
Also, if you are doing individual videos, the VideoPlayer is much lighter weight, and cleans up nicer.
Thanks for the responses, the links to the other blog questions were helpful as well, I had read all of Grant Skinner's info on garbage collection too, but searching through those links and going back and re-reading what he had originally said about GC helped refresh the old noggin. In addition to nulling and re-instantiating that single FLVPlayback component, I also realized that I wasn't correctly unloading and destroying my Loader instances either, so I got them cleaned up and now the program is running much more efficiently. I would say the memory usage has improved by around 90% for the site.
#aib I will admit the single instance solution isn't elegant, but because flash just won't let go of those FLV files, I'm kind of stuck with it.
#grapefrukt I detest the flash components, they typically cause more grief than time saved, however in this case I had a lot of cue points and navigation stuff going on with the video files and the FLVPlayback component was the best solution I found. Of course I'm still fairly new to the ActionScript world so perhaps I over-looked something.
Unfortuantely, thats just the way flash handles it. Not particularly smart, but it works for most people.