I started running into serious issues with the garbage collector partially picking this up, but still leaving most of the object up and running in the background without a reference:
m_win = new MyWindow(arr);
m_win.open();
m_win.addEventListener(Event.CLOSE, onClose);
.
.
.
private function onClose(pEvent:Event):void
{
m_win.removeEventListener(Event.CLOSE, onClose);
m_win.close();
m_win = null;
// RAM usage for m_win is only reduced about 20-40%. I can see the garbage
// collector has run as a result of that reduction, but the other 60-80% are
// a serious problem.
}
That's the only event listener I have added to m_win, and that's the only reference my code has to m_win. MyWindow is basically a standalone AIR project (although it's nested in a different class than its own Main class to adapt it to work for this scenario; otherwise the same). MyWindow has NetConnections, NetStreams, and such that were kept live after the garbage collector would run.
So one of the first things I tried was to go in and disconnect its NetConnections and NetStreams. But that didn't work. Then I came across these blogs:
http://tomgabob.blogspot.com/2009/11/as3-memory-management.html
I found the link for that in another blog from another guy who had trouble with the same thing: Supposedly if AS3's garbage collector finds an "island" that has reached a critical mass (in my experience, maybe 30 MB?), it just refuses to do anything with it. So I went with this guy's recommendation and at least attempted to null out every reference, remove every event listener, call removeAllElements() and/or removeChildren() where necessary, and call "destructor" functions manually all throughout MyWindow, the sole exception being the Main class that isn't really used for m_win.
It didn't work, unless I messed up. But even if I left a couple of stones unturned, it should have still broken up the island more than enough for it to work. I've been researching other causes and work-arounds for this problem and have tried other things (such as manually telling the garbage collector to run), but nothing's cleaning the mess up properly. The only thing that has worked has been to disconnect the NetConnection/NetStream stuff on the way out, but a good 25-30 MB is remaining uncollected.
How can this be fixed? Thanks!
EDIT: Given Adobe's statements at http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/garbage-collection.html:
"GCRoots are never garbage collected."
and:
"The MMgc is considered a conservative collector for mark/sweep. The MMgc can't
tell if certain values in memory are object pointers (memory addresses) or a
numeric value. In order to prevent accidentally collecting objects the values
may point to, the MMgc assumes that every value could be a pointer. Therefore,
some objects that are not really being pointed to will never be collected and
will be considered a memory leak. Although you want to minimize memory leaks to
optimize performance, the occasional leaks that result from conservative GC tend
to be random, not to grow over time, and have much less of an impact on an
application's performance than leaks caused by developers."
I can see sort of a link between that and the "big island" theory at this point - assuming the theory is correct, which I'm not. Adobe's pretty much admitting at this point, in at least the second statement, that there are at least benign issues with orphans getting skipped over. They act like it's no big deal, but to just leave it like that and pretend it's nothing is probably mostly just typical Adobe sloppiness. What if one of those rare missed orphans that they mentioned has a large, fully-active object hierarchy within it? If you can't prevent the memory leak there completely, I could definitely see how going through and doing things like nulling out references all throughout that hierarchy before you lose your reference would generally do a lot to minimize the amount of memory leaked as a result.
My thinking is that the garbage collector would generally still be able to get rid of most of everything within that island, just not the island itself. Also what some of these people who were supposedly able to really use the "big island" theory were seeing was probably some of the "less benign" manifestations of what Adobe was admitting to. This remains a hypothesis though.
EDIT: After I checked again on the destructorsand straightened out a couple of issues, I did see a significant improvement. The reason I'm leaving this question up and going is that not only is there a chance I'm still missing something else I could be doing to release memory, but the main explanation I've used so far isn't official or proven.
try calling
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}
// the GC will perform a full mark/sweep on the second call.
to force garbage collection. This is undocumented, but works.. credits to Grant Skinner, who explains more on his blog
Related
In our application framework ,whenever a code duplicate starts happen (even in slightest degree) people immediately wanted it to be removed and added as separate function. Though it is good ,when it is being done at the early stage of development soon that function need to be changed in an unexpected way. Then they add if condition and other condition to make that function stay.
Is duplicate really evil? I feel we can wait for triplication (duplicate in three places ) to occur before making it as a function. But i am being seen as alien if i suggest this. Do we need to avoid duplicate at any cost ?
There is a quote from Donald Knuth that pin points your question:
The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming.
I think that duplication is needed so we are able to understand what are the critical points that need to be DRYed.
Duplicated code is something that should be avoided but there are some (less frequent) contexts where abstractions may lead you to poor code, for example when writing test specs some degree of repetition may keep your code easier to maintain.
I guess you should always ask what is the gain of another abstraction and if there is no quick win you may leave some duplicated code and add TODO comment, this will make you code faster, deliver earlier and DRY only what is most valued.
A similar approach is described by Three Strikes And You Refactor:
The first time you do something, you just do it.
The second time you do something similar, you wince at the duplication, but you do the duplicate thing anyway.
(Or if you're like me, you don't wince just yet -- because your DuplicationRefactoringThreshold is 3 or 4.)
The third time you do something similar, you refactor.
This is the holy war between management, developers and QC.
So to make this war end you need to make a conman concept for all three of them.
Abstraction VS Encapsulation, Interface VS Class, Singleton VS Static.
you all need to give yourself time to understand each other point of view to make this work.
For example if you are using scrum then you can go sprints for developing then make a sprint for abstraction and encapsulation.
What's better?
1000 objects with 500 lines of code each
vs
1000 objects with 30 lines of code each that delegate to one manager with 500 lines of code.
Context:
I have signals in my game. Dozens and dozens of them. I like that they have better performance than the native Flash Event.
I figured that as I was going to have so many, they should be lightweight, so each signal only stores a few variables and three methods.
Variables: head, tail, isStepping, hasColdNodes, signalMgr
Methods: addListener, removeListener, dispatch
But all these signals delegate the heavywork to the signalMgr, as in:
signalMgr.addListener(this, listener, removeOnFirstCallback);
That manager handles all the doublylinked list stuff, and has much more code than a signal.
So, is it correct to think this way?
I figure that if I had all the management code in the signal, that would be repeated in memory every time I instance one.
In the context of your question this is pretty much irrelevant and both cases should not produce much difference.
From what you say it seems that you assume many things but did not actually check any. For instance when you say: "I like that they have better performance than the native Flash Event." I can only assume that you did read that somewhere but never try to verify it by yourself. There's only a few cases where using the signal system can make a tiny bit of difference, in most cases they don't bring much, in some cases they make things worse. In the context of Flash development signals do not bring anything more than simple convenience. Flash is an event driven system that cannot be turned off so using signals with it means using event + signals, not using signals alone. In the case of custom events using delegation is much more efficient and easier to use and doesn't require any object creation.
But the real answer to the question is even more simple: There's no point optimizing something that you don't know needs optimization. Even worse different OS will produce different optimization needs so anyone trying to answer a general optimization question can only fail or pretend to know.
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. (c) DonaldKnuth
The ultimate goal of any programmer is to write clean code. So you should write clean code with a only a few thoughts of optimizations.
I am working on how to reduce the memory usage in the code and got to know that removing the component also remove its children present inside it.If this happens the memory usage must decrease but it is increasing.
I have a titlewindow which contains of hboxes and those hboxes have canvases as children which contains images. Now if i use removeChild(titlewindow)
Does all the hboxes, canvases and images present in it gets removed or not?
If gets removed the memory usage is reduceed or not? How can i do that in flex?
Yeah, everything pretty much gets removed with it, as long as you then set the value of titleWindow to null and don't ever re-add those children. As for whether this clears out any memory or not, it basically will under two conditions:
The garbage collector runs afterwards. This can be expensive, and thus Adobe's designed it to not necessarily just keep happening over and over again at regular intervals. Instead it tends to happen when Flash Player or AIR is running out of memory in its current heap, at which point the garbage collector will check first to see if it can free up enough space within the current heap before anything more is grabbed from the operating system.
You don't have any non-orphaned references to these children anywhere else. By "non-orphaned", I mean that if the only places where you still have references to them are themselves without any references in the rest of your program, this condition is still met.
There is at least one exception to this rule, and that is that the garbage collector can single out multiple objects in your program as GCRoots. A GCRoot is never garbage-collected, period. So if you orphan off a GCRoot (make it so that neither it nor any of its descendants have any references anywhere outside of themselves), the garbage collector basically just doesn't care. The GCRoot will be left in there, and any references it has to any objects are thus considered live and active. Additionally there are certain occasions when the garbage collector will simply not be able to tell whether something in memory is a reference or not, so it'll just assume that it is and potentially fail to delete something. Usually this is not a problem, but if your program is big enough and is not doing a lot of object-pooling, I can tell you from experience that reacting specifically to this can on rare occasions be a necessity.
Try setting the titlewindow to null after removing them:
removeChild(titlewindow);
titlewindow = null;
The garbage collector will remove all your boxes from memory if there are no more references to them from your main code. It should be okay to ignore explicitly removing the children, as long as the only references to them are from the parent, i.e. titlewindow and its children are an isolated group of objects. But make sure you also remove any event listeners that anything might have registered to with removeEventListener().
Also, there is no guarantee when the garbage collector actually runs, so if it looks like your memory is increasing, it might just mean the GC hasn't had a chance to clear up the memory yet. Here's an SO question on how to force GC to run. (when debugging, System.gc() usually works for me).
so, in a nutshell, my question is pretty much in title, I have my first big project and now after 11k lines of code in one big file I am running into memory issues after a while I have tried out my flash, slowly it slows down until I cant do anything, even if I always clear containers when I can and remove listeners when not needed.
procedural, for those who dont know, I have everything in big main function and within that hundreds of other functions.
oop logic feels a bit too big of thing to try and understand at this point, procedural so far has been much more natural to me...
any tips how to prevent memory from running out?
You don't really need any object oriented programming to break it down.
Just apply a bit of logic of where you can group & separate things. Also, chances of repetitive lines of code is very high too.
So first of, start grouping lines. put them inside different functions & call them in main.
After you bring it all down to chunks, you can start thinking of grouping the functions into classes as well. But at the very least the first step should have brought your problem down.
Your problem is hard to solve without using object-oriented programming. Btw, the C style of coding is usually called "imperative programming"... just so you know.
The bad news is, 11k lines of code in one file means all the code is inside one translation unit, so everything you coded is always in memory.
If you break it up into classes, then individual class instances (objects) will be created and destroyed on a requirement basis, thereby taking up as much memory as needed (growing and shrinking, not static).
Finally, using as3 as if it were C will hurt you in many other ways long-term. So please learn OOP and break up your monolithic code into objects.
Well afterall calling this a bad practice, you may not giving VM (virtual machine) a chance to breath... I mean If your procedures goes on busy everytime in a loop like thing polling states then with great probability the VM does not find the opportunity to garbage collect. Which is a disaster.
So do not poll events if you are doing. Try getting rid of the grand procedure (the seer of all :) ) and try another architecture which the central monitor procedure is invoked by event handlers when needed.
Then when you settle, sell your product and get rich. Learn oop a.s.a.p. :)
have developed a touch screen stand alone application. The interactive is currently running 10 - 13 hours per day. If the user interacts with interactive the memory level is going on increasing. The interactive has five screens while travelling through each screen I have removed the movieclip, assets, listener's and I set objects to null. Yet the memory level keep increasing.
Also I have used third party tool "gskinner" to solve this problem, It improves the result even though some memory leakage is there.
Please help me, thanks in advance.
Your best results will come from writing the code in a way that elements are properly garbage collected on removal. That means removing all the objects, listeners and MovieClips/Sprites within that are no longer used.
When I'm trying to get this stuff done quickly, I've been using casalib's CasaMovieClip and CasaSprite instead of regular MovieClips and Sprites. The reason is that they have the destroy() functions as well as some other functions that help you garbage collect easily.
But the best advice I can give is to read up on garbage collection. Grant Skinner's blog is a great place to start.
Also, check for setTimeout() and dictionaries, as these can cause leaks as well if not used properly.