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.)
Related
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.
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.
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.
I have a question how can I clear/free memory in flash? For example I am finishing game and I want to start from beginning and if I will just jump to the first frame all the objects there are still in this memory, is any possibility to force cleaning memory?
Can I free memory for an object? for example I removeChild(something) - and I want to free memory for an object as I will reuse it?
Can anybody explain me how the engine works?
Thanks
I would encourage you to read Chapter 14, Garbage Collection in the "Moock Book" (Essential ActionScript 3.0 by O'Reilly Publishing).
The short answer to your question is that you're not in control of de-allocation, the garbage collector is. In a garbage-collected language like AS3 or Java, you don't have manual control over allocation and de-allocation of memory like you do in lower level languages; there are no AS3 equivalents to things like delete in C++ or free in C. Your goal should not be controlling when you destroy things, but rather not forgetting to remove references to things you no longer need around and making sure you disable things that you intend for garbage collection.
Memory leaks in AS3 typically come from a mixture of newbie misunderstanding (like thinking removeChild or setting a reference to null destroys objects), and from not keeping good track of references to objects--especially where strong listeners are involved.
A previous respondent posted this:
myObject = null;
What this does is remove a reference to the object that the variable myObject was holding. Nothing more. You need to know a lot more about the situation in order to be able to say whether this assignment even makes the object in question eligible for garbage collection, especially how many other variable are holding references to the object. And the object might already be eligible for garbage collection even if you didn't set the reference to null (i.e. if myObject has no connection to a GC root).
Suffice to say, the entire GC mechanism is more complex than can be satisfactorily explained in a StackOverflow post. That's why it has a whole chapter in the Moock Book, and even that book does not go into implemenation detail or great detail about when exactly the Flash Player does its ref counting deletions or mark and sweep passes.
The most important things to remember are, IMHO:
When you intend to "kill" an object, give it a cleanUp() or destroy() function where you do things like stop all its timers, sounds, remove listeners, etc. An object will continue to exist and execute code until it gets GC'd. And the Flash Player defers GC as long as it can--it's usually triggered when the Player needs to allocate more RAM from your system, because allocating memory is about the only thing that's more time consuming than doing the mark and sweep GC pass.
Read about weak vs strong listeners. Basically, when you have a weak listener, the listener reference is one that is ignored by mark-and-sweep GC, so it alone will not prevent an object from getting collected. But don't listen to anyone who tells you "always use weak" or "always use strong listeners and manually remove them" because there are times where each is appropriate, and that's why the choice is yours.
removeChild() will remove object from stage, but will still keep it in memory. You will have to null the object like this myObject = null if you wish to get rid of it entirely. You might not need to do that thought. Just removing it from stage and removing all associated events will be sufficient in most cases.
Clearing memory is a tricky thing with Flash, the proper way ow implementing it setting up objects properly in the first play for easy clearing, rather than forcing deletion. When you want to remove an object from memory, you do it by removing any reference to it, and then flash marks it for garbage collection. Then Flash at a later point removes the object from memory.
In order for the object to be ready for data collection it cannot have any connection to another object.
so if you have an object that has a single connection to a MovieClip and the movie clip has no other relation, then if you set it to null, you will remove it.
if you, however, have two objects that point to it, if you remove one link by setting it to null, the MovieClip will not be removed.
furhtermore, if you have a 2 or more movie clips that have a network of connections, removing those objects requires these connections be broken as-well. For example if you have a level with many characters and listeners set up, removing the lavel movieClip will not clear it.
one way of breaking these connections is adding onRemovedFromStage Events, that remove further children, listeners and objects. I've started using the casaLib extension of movieclip - CasaMovieClip, that has a function called removeChildrenAndDestroy. this makes it a bit easier, but would take a while to implement on an older project.
Anyhow, you'll find there are many sites discussing this, a good place to start is grant skinner's blog
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.