Or… how to kill a user’s computer with 1 line of ActionScript.
I’ve been profiling CPU/RAM usage in Flash 8 content in the last few days in preparation for the Flash 8 Bootcamp I’m running in Toronto and LA. Last night I ran into a major memory leak that is wreaking havoc with some of my latest experiments, and this morning I isolated it. This leak makes it ridiculously easy to accidently create a process that increases the Flash Player’s memory heap at a very rapid rate, and ultimately immobilizes the user’s system (I’ve had to do a few slow motion restarts while testing this – I had over 15GB of virtual memory dedicated to the player at one point).
The problem is simple: The Flash Player does not ever dispose of BitmapData objects stored in function variables. This is easily reproduced by placing the following line of code in the timeline of a new FLA:
function onEnterFrame() { var foo = new flash.display.BitmapData(500,500); } |
Run it and watch the memory usage. It will increase by around 60MB per second. This is because the variable foo is not disposed of when the function finishes executing. As such, the BitmapData object remains in memory until you close the player. To clarify this (in response to a comment below), function variables are transitory – they should only exist during execution of the function. The Flash Player should always mark all function variables for deletion as soon as the function finishes executing. This occurs with other variable types, but does not appear to be working properly with BitmapData objects.
In many scenarios, you can avoid this problem by using BitmapData.dispose to explicitly remove your bitmaps from memory.
function onEnterFrame() { var foo = new flash.display.BitmapData(500,500); foo.noise(1); foo.dispose(); } |
This does not work if you want to attach or return the bitmap however, because dispose deletes the actual bitmap data in memory, not just the reference.
function onEnterFrame() { var foo = new flash.display.BitmapData(500,500); foo.noise(1); mc.attachBitmap(foo,1); foo.dispose(); // The bitmap will not be show up because it no longer exists } |
There are two obvious ways to work around this, which can be a little messy, but work in almost all scenarios. The first approach is to always reuse bitmaps. This is more efficient anyway, because bitmaps are expensive to instantiate and destroy, but it isn’t always possible or desirable.
foo = new flash.display.BitmapData(500,500); function onEnterFrame() { // reuse foo: foo.noise(1); mc.attachBitmap(foo,1); } |
The second way is to hold on to a reference to the bitmap, so that you can dispose of it later.
foo = null; function onEnterFrame() { // dispose of the old bitmap: foo.dispose(); foo = new flash.display.BitmapData(500,500); mc.attachBitmap(foo,1); } |
It is also important to remember to dispose of any interim bitmaps you use for calculations.
function displaceStuff(p_bmp) { var mapBmp = new flash.display.BitmapData(500,500); // do stuff mapBmp.dispose(); return p_bmp; } |
I hope this helps you avoid this problem for the time being, and hopefully Macromedia releases a FP8.1 update at some point to fix this dangerous issue. The last thing we need is for Flash to drop its reputation for being a toy to build intro animations and pick up a reputation for crashing user’s systems instead.
Update: I’m continuing to look into this, it’s interesting to note that the bitmaps are not cleaned up even if placed into an object in a function var. This does appear to only occur with BitmapData objects – I’ve tested the same scenario with large arrays, and the memory heap never increases. I’ve also tested to ensure that BitmapData objects are properly disposed in other situations, and it appears they are cleaned up when all references are removed. Stranger and stranger.
I ran into this while testing the beta.
I never create new instances of bitmapdata on enterframe.
creating the bitmap data object before and just doing operations on it is of course a better option.
thank you for your detailed description
ciao.ubi
I wouldn’t consider it as (MAJOR) leak. That’s what should happen when you start giving users more power. Do you see any other way it could have been implemented?
Cheers, chr
Christian,
Sorry for not being more clear about how this should work. I’ve added the following: To clarify this (in response to a comment below), function variables are transitory – they should only exist during execution of the function. The Flash Player should always mark all function variables for deletion as soon as the function finishes executing. This occurs with other variable types, but does not appear to be working properly with BitmapData objects. My guess is that the variable is flagged for deletion, but the garbage collector is not disposing of the bitmap properly and freeing the memory.
Thanks for the clarification. Of course, you are right! Don’t you think it could be because when instantiating a new flash.display.BitmapData the player creates an instance of the object outside the class, maybe for rendering issues? It’s strange that is just a banal flag. Probably we should try with different objects to see if it does the same (of course it will be difficult to fill 15 gb of virtual memory with components :D)
I’m with Christian, I can see you’re technically right Grant, but it’s hardly a major flaw. However I’m interested to know what you’ve been working on that prompted you to bring this up. Creating many bitmapData instances onEnterFrame seems pretty unnecessary as I see it so I’d love to see what you’ve been building because I know you are a far better programmer than me and you wouldn’t be doing it without a good reason.
I think it’s a big problem. It makes it very easy to inadvertently generate a massive memory heap. Consider that a single 500×500 bitmap takes 1MB in memory, and apply that to a site that someone might have open for 20 minutes. Even if you are only generating bitmaps intermittently, the memory usage will get inappropriately large.
I have built a series of bitmap utility methods that perform tasks I use frequently in my newer experiments. These methods need to create temporary bitmaps to perform comparisons and calculations, and they frequently return a new (or cloned) bitmap. The former is easy to deal with, I can just .dispose the temporary bitmaps when I’m done with them. The latter is a pain in the arse – I can’t dispose the bitmap in the function because I need to return it. I can’t cleanly dispose of the bitmap in the calling function because I want to attach it. So I wind up creating hacks to hold on to bitmap references for later disposal as outlined above.
Sure, you and I can (and will) work around these problems. It’s a minor pain in the butt, but not a big issue. The real issue is with the 990,000 Flash content creators that will never read this post and will be unaware of this leak. We only need a tiny fraction of a percentage of these developers to inadvertently create swfs that take down users’ systems to cause major damage to Flash’s reputation.
I personally think the Flash player should have a memory cap to minimize problems like this, and more malevolent content (it’s super simple to write a swf that would immobilize your system in seconds).
Nice find.
Good find and I agree with Grant that this is a big problem. And interesting timing because no more than just a few hours before seeing this post I discovered a big leak in Flash Remoting where if you pass an object larger than a few hundred k to the service, the player grabs about 40MB of memory. And of course the exact code worked swimmingly in the 7 player.
Essentially it’s a garbage cleanup issue. I thought the new garbage collector would fix this kind of stuff. Are bitmaps treated differently by the GC? The question arising in this discussion is more or less if this is or should be on purpose. Having seen Gary’s session on the new GC in the 8 player I think not. Strangly enough this shouldn’t be an issue at all. When there are no references to the bitmapdata object anymore, it’s token count should go to 0 and the GC should pass it, and clean it up. I don’t really think this has been implemented this way on purpose.
So we need the MM people to come in, and tell us what the exact issue is…
Anyone? Tinic? Gary? Paul ? 🙂
Just did a quick check in AS3 / FP8.5…as to be expected, it’s in there too.
http://www.unitzeroone.com/blog/flash/grants_flash_8_memory_leak_is.html
Hi Grant,
I can explain what’s going on. Its not simple so buckle your seat belt. The FP8 heap is split into two, one area for GC objects and one area for unmanaged memory. GC objects are strings, objects, arrays from your program and some internal objects we use in the AVM and unmanaged memory are things like bit buffers such as like BitmapData allocates under the covers. What’s going on here is that the unmanaged memory is growing out of control and the GC or managed memory isn’t (the BitmapData object itself isn’t that big). We only trigger a GC when the managed memory gets tight. So one fix we could explore is allocating the bitmap buffer with managed memory.
However the player also employs ref counting and the ref count to your bitmap object should drop to zero and get reclaimed after each invocation right? Not so, because we employ an optimized version of ref counting that doesn’t count local variables as references. The BitmapData object in your example never gets a references, its ref count stays at zero and it stays around until the mark sweep collector comes and gets it, as if it were involved in a cyclical reference. So a work around would be:
function onEnterFrame() { foo = new flash.display.BitmapData(500,500); }
Now instead of storing the BitmapData in a local variable we store it in the global object under the name foo, since we have to ref count non-local references you’ll see the problem go away b/c ref counting kicks in like it should.
So there’s two issues we need to deal with:
1) Native AS objects that allocate unmanaged memory can be a problem cause they don’t influence the GC.
2) Objects that don’t escape from their allocation function don’t ever get a ref count and stick around until the mark sweep collector kicks in.
These two issues will be added to my 8.5 todo list but I don’t think there’s anything here that justifies a 8 patch.
Sorry for the inconvience!
Tommy
Tommy,
How do you recommend to use BitmapData in a class? Does a private field get treated as local variable or a global one?
Alex
Tommy,
Thanks for the info! That makes sense, even if the resultant behavior doesn’t. Just FYI – I wasn’t suggesting that this issue warrants a dot release on its own, merely hoping there would be a dot release to fix this and other issues before next spring.
The solution you mention is ugly, but it should work. I would recommend throwing references into a _global.tmp object, rather than putting them in _global unqualified. I’d also recommend deleting the reference the moment you’re done with it, so that it doesn’t rely on overwriting to clear the reference. Obviously this is not possible with functions that return a bitmap, but you could fall back on overwriting for those scenarios as long as you decided on a standard name for your bitmaps. You could set up an interval or enterFrame process that would reset the tmp object every few frames.
Alex,
A private field of a class is ref counted. Only stack references, local variables stored in registers and function parameters aren’t ref counted. That’s a big part of the reason FP8 executes actionscript faster than FP7.
Tommy
What I wonder though is what type of memory effect this may have on any variable used in an onEnterFrame method.
I’m sure there are many situations where variable may be created and destroyed in onEnterFrame, and leaving the Player running for a very long time may expose that weakness that Tom discussed.
Great find though – I’m suprised none of us noticed that during testing.
I think this is worth exploring to see if not just BitmapData objects are affected…
Grant said: “I can’t cleanly dispose of the bitmap in the calling function because I want to attach it. So I wind up creating hacks to hold on to bitmap references for later disposal as outlined above.”
Sounds like C++ or programming in OpenGL where you do need to hold on to references for disposal, or otherwise you do create a memory leak. 🙂
In that case it’s a FOL when dealing with compiled languages. GC can only take a developer so far.
As the Flash platform progresses, especially with the release of AS3, more doors will open to us. Those doors won’t always be safe to go through.
Jon,
Of course Uncle Ben said it best “With great power comes great responsibility”. I agree with this to a point. However, I do not want to see Flash regress. Most languages grow more managed and abstract as they mature, whereas AS is actually becoming less so in many respects. I don’t want to be reduced to writing assembly (byte code?) and assigning memory manually in AS5. 😉
We’re also dealing with a much different environment than desktop programmers. If you build a buggy, leaky app for the desktop few people will be exposed to it, and no one will blame the technology. Buggy, leaky content in Flash is likely to be consumed by millions, and you can bet that it will reflect on Flash as a technology (especially with slashdotters raising hell about it). Many of the developers in the Flash world also don’t have the formal programming backgrounds to successfully deal with memory management and other low level tasks. They will learn, but I worry about the transitional period.
My thought is that if the language is going to evolve to make it easier to write content that will seriously impact users’ system stability (or conversely, harder to write content that won’t), the player must also evolve to include safeguards against malicious or poorly written apps. If not, the mistakes of the few will impact the perception of Flash as a whole.
Grant:
I agree with your sentiment of not wanting AS to evolve in the direction of having to manage memory usage directly.
So not to suggest this idea as a real improvement per se, but reading your idea about a qualified _global.temp variable made me think of Objective-Cs autorelease pool. With the autorelease pool you send instances retain messages when you want a persistent handle to them, which increments their reference counter by one, and send them release when you’re done with them, which decrements their reference counter.
Every event cycle the autorelease pool checks it’s members for those with zero references, and deallocates them.
So one could implement an autorelease pool… usage might look like:
AutoreleasePool.retain( myBitmap );
– or –
AutoreleasePool.release( myBitmap );
The pools cycle could be driven by an onEnterFrame loop. You wouldn’t want to retain these objects inside the method where you’ve created them as a local instance with the intent of returning them, so for that usage maybe we’d want
AutoreleasePool.add( myBitmap );
which would add it to the pool, but not increment the reference counter.
Again, not suggesting as some kind of long term solution, just a potentially useful interim fix.
i couldn´t agree more with that last comment of yours Grant.
I experienced that memory leakage with earlier builts of the f8 player already but i couldn´t clearly narrow the problem on its center to get the reason. I was just doing a lot with bmpData and checking and rechecking my code i couldn´t find a reason why the bmpDatas weren´t removed from memory, so i just wrote mm Feedback stating my problem in general (and thought it was actually fixed with the full version player,didn´t get back to those experiments since then).
Now after the previous explanations here it seems like i was doing exactly the opposite (by using local variables for handling bmpData objects) of what is actually working.
The explanation Tommy gave made sense but as you said the result doesn´t at all and is clearly against all coder logic at that point.
Yeah, its good AS is evolving but i totally agree that it shouln´t go more and more low level forcing the developer to think about how to avoid memory leakage for such basic usage scenarios, especially not in a way which doesn´t make any sense at all from the coder perspective.
I´d also highly appreciate it if this was sorted with one of the next VM builts as i wouldn´t like it much either seeing the “new flash brings memory leakage problems” posts on the slashdotters side once more flash8 content is around where maybe the developers didn´t know about the issues and workarounds explained here.
THIS IS NOT EVEN CLOSE TO BEING A PROBLEM OF ANY SIGNIFICANCE!!!
Actionscript is maturing from a beginners scripting tool to a robust, scalable and enterprise ready language. With this comes a lot of responsibility and education. Actionscript developers now have to realize that they are no longer in Kansas and that they are going to have more power and they are going to have to learn how to use it effectively. This is not Macromedia’s responsibility, but the sole responsibility of the developer!.
For developers that come from a more traditional C background this is nothing new. All the bitmapData API is doing is allocating memory and the prevailing rule of thumb with memory allocation is…”If you allocate it. You must track it!”. Essentially the bitmapData API is like using the malloc statement in C. In C every-time you use the malloc statement you have to keep track of it because you may need to free a particular memory block in the future. The same thing is applied with the bitmapData API by using the dispose() method.
My concern is that by setting off false alarms the Macromedia engineers might think twice about adding new and more powerful features simply because they may believe that we do not have enough knowledge to handle the responsibility.
erm…right…
Did you even read the previous comments completely?
I can only speak for myself but i surely didn´t argue against adding new and powerful features, neither was that my aim of course
(and i´m sorry if the smallest gripe on how something is implemented leads to not implementing new things at all anymore, because that would surely be the wrong bottom line).
I´m not against having to learn how to handle new features to be able to use them; i´m against having those features working in a way which contradicts to common coder sense and the way the rest of the code implementation works.
It just does´t make much sense from the coders´ view that something defined as local variable exists and is persistent outside the function/object scope, that´s the point.
Tom,
I hear what you are saying. But in this case it does make sense from a coder’s view. The bitmapData class is working exactly as it should. Remember the variable that holds the instance of the bitmapData class in the stack is removed ( Flash GC is working correctly ), but the heap hasn’t been cleaned up, that’s the job of the coder; i.e. “You created space on the heap you must remove it when you are done”. As for contradicting common coder sense I think it’s just that Actionscript developers are not used to dealing with these kinds of issues-this level of control and expressiveness through Actionscript is new to us- but with proper education it will become second nature!
Personally I would love it if Macromedia gave us access to the heap! That would truly be a very powerful feature. Ah… but one can only dream.
😀
Samuel I have to disagree. This is not C and the cleanup is the responsibility of the garbage collector. MM has strict control of the code execution and needs to fine tune the avm. If one line of code can bring a system down, it wont take much for IT managers to once again ban the Flash player from builds and corporate intranets. Not to mention the potential security risks from nonsense arising from out of control memory allocation.
I hope we continue to move forward in programming technology where garbage collection affords us the luxury of not specifically dealing with memory allocation a la C and C++.
Randy,
The only reason IT director’s blocked flash was because of the annoying content that would pollute people’s screens ( the roaches running around in a banner ad ). If anyone needs to get beat-down it’s the morons the product that annoy $#!t.
A while back I remember helping a friend debug a similar problem in a JAVA program that he wrote for a large corporation. At the time Java had some issues with the concatenation of strings, causing large sums of heap memory to be consumed. IT, at the company did not ban Java cause of this! They blamed the guy that wrote the code, not Sun Microsystems. He bears the responsibility even though the JVM had issues. When a developer commits to a technology he/she has to make sure that what he/she develops using that technology, does not corrupt or harm the end user’s experience.
I agree that this is not C, however those basic fundamentals of computer programming are applicable to higher level languages including Actionscript. As developers we have to be conscience of that and code according.
All I’m saying is that before we ring the panic buttons we need to make sure that the situation merits the response. In my opinion this is much ado about nothing. Bottom line… Code defensively… not offensively!
cheers
😀
Sam,
i see your point, and sure, as a coder knowing about this issue, its no problem imho to just do it in a way which doesn´t lead to memory leakage (no matter if i think its reasonable how that is implemented and all).
(yeah,sure i can call dispose on a bmpdata which was instantiated as local variable to make sure memory is freed once i leave the scope i needed it in)
You stated an example where someone created content for a client and then the client blames him, not the environment or language when something in the product doesn´t work well.
And sure,for many cases that´s the way it would work.
Its different though for web content viewed by masses without them ordering the content directly.
When people view a webpage with flash content and that page leads to memory leakage after a while (maybe even after a short while), they normally won´t go to the company/individual who created that content to tell them they made a fault there and should fix it.
Normally people who still like the technology overall just don´t visit that site anymore, informed ones maybe thinking the memory leakage is the fault of the content creator,not the used technology. But people who are not that much into flash and “just” interested in the stability of the machines in their network normally turn of technologies which might affect that stability in a way quite quickly (not speaking specifically about flash, i just have to deal with clients a lot who have this or technology turned off in their network for stability or security reasons and one has to do the requested project in another technology then which in some cases is the worse option).
I wouldn´t see it as such a problem if thinking about how to avoid memory leakage would only be needed when doing really complex things in low level way. Because then the group you named uneducated developers would probably not likely get into the situation to use them that way. But instantiating a bitmapData Object will be quite a common everyday thing many people will do in their f8 projects and surely most of those don´t have a c/c++ background. They will just do it the way they normally do their (maybe in ideal case oop manner ) code. That would be creating a local variable and not beeing worried anymore if its deleted from memory as they expect it..
Up to now flash has always been a high level language, i didn´t hear any flash developer talking about the way the garbage collector of flash works in the past. Neither how to do things in a way to avoid memory leakage to do basic things.
With the new flash player a new garbage collector is introduced which works better if objects are reused rather then constantly creating new ones in short timespan. That alone,though a really basic thing already makes flash a bit more low level, as suddenly the developer caring about performance should think about the way the gc works and how to do things matching that concept ideally.
Still,no biggy, of course,doing it “wrong” won´t freeze the system right away or lead to other major impacts;just to a slightly less stable/performant result. With such things like thinking about when local variables are deleted and when not it goes a good step closer to low level though. Again,if there are two ways to do something,one is the basic way,maybe not leading to ideal performance and flexibility and the other the more complex to implement way,maybe leading to more flexibility and performance but also involving more responsibility regarding how to handle things like those discussed here,doing things in a way in which one avoids memory leakage, i wouldn´t see a problem there.
Designers and other groups not that used in low level coding would probably automatically go the easy way where they can avoid thinking about such things they don´t want to think about.
But as it is now,doing a basic thing involves thinking about such issues. So its not really speculation to imagine the amount of flash ads and sites which will lead to memory leakage with the way people would implement them following their ordinary coding logic (speaking about their ordniary coding logic as in high level oop manner,not as in coming from c/c++ and automatically thinking about the low level side of things).
I´d like a solution where there would be the advanced way of the bitmapdata handling (and handling of other things),where you´d have even more control over the heap and would have to think about the responsibility on the other side and on the other side the basic way for non low level coders who don´t want that much of control over lower level things and can expect that (no matter how its done internally,maybe just dispose being called on all bmpdatas instantiated as local variable once the function/object scope is left); when instantiating a local variable they don´t have to mind about it outside the function/object scope.
You can´t really say there´s more power leading to more responsibility for a language/environment used on the web. Because neither are the developers using that environment all on the same or similar level nor are the consumers using the content always freely deciding if they see that content in that moment. If you just give one way of how to implement something,it has to be the foolproof way where noone has to do it in a certain way to avoid memory leakage or other low level issues. So a decission should be made there, do we want to let flash go towards beeing a more low level language or do we want it to be a high level language. Or, third case, do we want to offer several implementation ways for many things so each developer group can pick the one which they like and which they can handle,low level way or high level way.
(As you can imagine i´d enjoy option 1 (completely high level) or option 3 (offering several implementations,one for high level and one for low level),what i wouldn´t like is seeing lots of content done with an implementation which is how designers or high level oop coders would do it typically and which makes my machine turn slow down or freeze when i surf the web in a free minute.
Is this not a similar issue to making sure that intervals are cleared and listeners removed? Isn’t it all just part of being a good boy and putting away your toys when finished playing?
No, this isn’t a similar issue at all. SetInterval has a predictable and documented usage / results. This issue does not.
As has been explained many times above, this is a matter of the GC behaving in an unexpected manner. Memory for function variables is supposed to be automatically deallocated after the function has completed execution. That is not happening here.
This is a bug, it has serious potential implications, and it should be fixed, period. Suggesting otherwise is naive.
The arguments on developer responsibility have little bearing on the above, but I think they are interesting nonetheless.
Samuel – your arguments are contradictory. You are suggesting that IT directors block Flash simply because the content is annoying, but that they wouldn’t think of blocking it if it caused system stability issues. This is obviously completely untrue. If Flash gets a reputation for causing system instability, whether it’s due to bugs in the VM or just poorly written code, it will get blocked in a heartbeat.
Flash is a heavily branded, easily installed and widely distributed technology that provides no barrier to accessing content. This is hugely beneficial to us as developers and to our users, but it also means that the technology will always be judged in part on the content deployed with it. I don’t think it’s possible to deny this – we’ve had nearly a decade of proof of the phenomenon.
I am a strong advocate of developer responsibility, but I am also a realist. I know that for every responsible Flash developer creating great apps, there will be an untrained or lazy developer creating leaky/buggy content. One of Macromedia’s greatest challenges is going to be empowering the good developers, while safeguarding users from the rest.
Grant,
I believe you miss understood my point… When I said annoyances I was talking about flash content that was visually or audibly annoying, not technically.
I’m the first fellow to admit that Macromedia needs to clarify how the bitmapData API works in their documentation. But I still don’t believe it is a major issue and I certainly do not believe it will cause flash content to be undesirable.
Now like I stated earlier, unless an adopted technology has a serious flaw, IT directors will probably continue to use it. Just like the example I mentioned earlier, they will not blame Macromedia or Sun, they’ll blame the developer who developed the faulty software. For example I have to fly to a client’s HQ to discuss how we can integrate our existing flash based technology with their flex technology. If we would’ve developed code that would’ve cause the Flash Player to crash, our client would probably dismiss us and our faulty code and continue to look for another solution that fits with their Flex strategy without crashing their players. They wouldn’t just dismiss the whole Flash Platform!!
So when you say, “…but it also means that the technology will always be judged in part on the content deployed with it.”. is a little fatalistic. I mean c’mon there will always be a lot of bad content and bad developers. It’s the really Really good that can be created with a particular technology, that decides if that technology is worth adopting or discarding.
I believe that it is the developers responsibility to create software of the highest order. This may mean, that a developer will have to step out of his or hers comfort zone to ensure that quality software is produced. I don’t think this is a bug in the GC as just a new way of dealing with certain objects in Flash. It’s unrealistic to assume that Macromedia can develop a tool that empowers users and provides 100% safeguarding. That my friend, I believe is a where the true contradiction lies.
Grant, I see were your coming from but I will have to agree with MrMiles,
“It’s it all just part of being a good boy and putting away your toys when finished playing?”
cheers
😀
Alright, this is my last post on this – it’s becoming a little redundant.
I respect your opinion, but I really don’t understand it. I have trouble believing that a sysadmin who will block Flash simply because of annoying content won’t block it after it takes down a couple of his systems. Then again, I’m not a sysadmin, so maybe my priorities are backwards.
I think part of the confusion is that you’re alternating between users’ choices and clients’ choices. I agree that clients are a lot less likely to judge the technology based on poorly written content. However, clients will judge it partly based on user perception, and most users will judge Flash entirely on the content they view with it.
You obviously weren’t around during the “skip intro” days. Building and selling real solutions built in Flash was an uphill battle, because the technology (not just the specific content) had a stigma. I don’t want Flash to have finally grown out of that bad rep to gain another.
And again, this is not a matter of putting away your toys when you’re done. It’s analogous to your mom telling you NOT to put them away because the maid will do it, then punishing you for following instructions. It is a bug, not expected behaviour. It has the potential to cause major problems for developers who are programming properly. It should be fixed. Why defend it?
Hi Grant,
I just wanted to clarify that my question about good practice and putting away toys was a genuine question, and not some kind of a rhetorical refute.
The extent to which I can form any sensible comments regarding garbage collection / unmanaged memory / ref counters and mark sweeps is going to be very limited. However, I do 100% agree that the Flash player ought to have some kind of memory cap, in a similar fashion to the alert that’s thrown if code enters an infinite loop: “Flash is consuming an inordinately large amount of memory! Do you wish to continue?”. A large degree of Flash’s ubiquity is surely to do with the fact that end users don’t (and shouldn’t) have to treat it with the same level of precaution as EXEs, ActiveX components or similar.
Either way, it’s still definitely a good caveat to be aware of when developing. Thanks.
All this things are well taken down here. I will try to make some testings and I will inform you guys out there. And thanks to Grand for opening it. You surely is a genius.
GM
hello, I’m one of the not so avid programers you mentioned I just wanted to add that this turned into a major problem for me and am so glad to find some resolution, even though I haven’t fixed my problem yet but hope to soon. Mine is a loop that runs on a heavily beafed up alienware system, and to my surprise it ran out of memory after 7 hours!? how is that even possible?? was my thought for the last two weeks. I would have to say that I agree that these issues need to be addressed, a prompt would be excellent, especially if an avid programmer could turn it off to perform whatever genious task is at hand, but for the rest of us, we hack and copy and paste and really get into a mess fairly quickly as sound as flash already is. But many thanks for the labourious work and genious’s at hand who openly offer advice. As you all know it has greatly helped the community grow.
Grant and all,
I have found another type of out of control memory allocation that I have posted on a couple of different sites. This Flash 8 leak occurs when dragging around a large, zoomed, vector movie clip. I’m sure it’s also related to the GC scheme as discussed above.
I consider this leak even more serious as I have no control over it.
An example swf file is posted here:
http://www.kirupa.com/forum/attachment.php?attachmentid=29930
Just zoom in to 600 or so over a piece of text using the slider in the upper left. Drag the image around with mouse and watch the heap grow. I’ve observed 2 to 3 MB per drag of as little as 5 to 10 pixels.
The code for this example can be found here:
http://www.flashkit.com/board/attachment.php?attachmentid=48646
So what do the experts here think? The only workaround I can think of is to split up the map into smaller clips and load and unload them as the user moves over that section of the map.
I do not get any problem with the originally reported code.
Has this problem already been fixed with the FP8r22 release?
Also wondering if the problem has been fixed.
The problem is fixed in FP8.5 … still a problem in FP8r22
While Grant’s original problem may be fixed in the 8.5 player the leak I reported above is still there in the stand-alone 8.5.0.133 player. I have yet to hear if anyone at MM is working to fix it.
I went looking for the 8.5 update but couldn’t find one. I’m on a Mac running latest OSX release.
Flash 8.5 is in alpha stage and is available in their labs area.
http://labs.macromedia.com/technologies/flashplayer8_5/
I also just received a response from MM in their 8.5 Alpha forum that the memory leak I reported is a known issue in Flash 8.x.
I am facing what might be a manifestation of this problem with a very large corporate site that I am working on. So far I haven’t been able to track it down; I am not instantiating an BD objects in the way that Grant described, but nonetheless we are seeing a major memory leak.
To throw my opinion into the fray, I agree strongly with Grant here – I certainly wouldn’t mind having to track memory use and clean things up manually – but in Flash we are told that this will happen on it’s own. MM needs to either make sure that the automatic GC works correctly, or adequately inform developers that they have to do it themselves.
It’s not too difficult to manage the bitmap garbage collection by yourself but I too wish that Macromedia would take care of it automagically.
I wrote this simple BitmapManager class to take care of the problem:
=================================
import flash.display.BitmapData;
class BitmapManager {
public var data:Array;
public function BitmapManager ()
{
data = new Array ();
}
public function newBitmap ( UniqueID:String, width:Number, height:Number, transparent:Boolean, fillColor:Number ):BitmapData
{
if ( data[UniqueID] != undefined )
{
data[UniqueID].dispose ();
}
data[UniqueID] = new BitmapData ( width, height, transparent, fillColor );
return data[UniqueID];
}
public function loadBitmap ( UniqueID:String, id:String ):BitmapData
{
if ( data[UniqueID] != undefined )
{
data[UniqueID].dispose ();
}
data[UniqueID] = BitmapData.loadBitmap ( id );
return data[UniqueID];
}
public function deleteBitmap ( UniqueID:String ):Boolean
{
data[UniqueID].dispose ();
delete data[UniqueID];
return true;
}
}
=================================
This is a short example. Of course you will want to wrap other BitmapData methods (clone, for instance) too so you can keep track of all your bitmaps by their UniqueID’s.
Usage:
var render_bit:BitmapData = BitmapManager.newBitmap ( “render_bit”, scratch_mc._width, scratch_mc._height, true, 0x00000000 );
vs.
var render_bit:BitmapData = new BitmapData ( scratch_mc._width, scratch_mc._height, true, 0x00000000 );
=================================
Need to dispose () every bitmap in your app? Iterate through the BitmapManager.data array.
You really do need to use dispose () to free up memory. Deleting the associated variables alone isn’t enough.
Just to let everyone know, the version of the memory leak I reported has been FIXED in the latest 8.5 alpha release (8.5.0.212) that is available here:
http://www.macromedia.com/cfusion/entitlement/index.cfm?event=custom&sku=RC00184&e=labs
Note: to get the stand-alone version you’ll have to install the full Flex 2 Builder beta.
I’m interested to hear some opinions on the situation Gary presented late in this thread.
Having just encountered the issue in one of my applications, I quickly found numerous references on different forums.
When applying the 2-heap/unmanaged memory explanation to Gary’s draggable MC, I’m not seeing this GC implementation as the culprit. The draggable issue could be duplicated with VERY LITTLE AS at all, which trumps the whole “coder responsibility” argument completely. If a designer with no programming experience can duplicate this memory leak, at what point are we going to place responsibility on the software developers?
In addition to that argument, another important detail has not been mentioned (sorry to be a johnny-come-lately, but I just discovered this amazingly detailed, extremely insightful post today!)
This second issue deals with scalability. These issues are not specific to F8 features, rather they have been caused by an implementation change in a major software release. New features and abilities aside, if a SWF developed, tested and deployed last year suddenly begins crashing user’s systems after a Flash Player upgrade, how can the creator of that content possibly be “blamed?” This, I think, is the biggest problem.
All coding experience aside, this problem was created the day MM began distributing Flash Player 8.
Hi All
I have two flash objects placed on my webpage and i am using external interface class to communicate between javascript and flash . The flash objects are in form tag. Now the issue is when i refresh the page it says out of memry? whats the solution. It works fine with one flash object ,not with two or more
all flash object have different id
man, i am so sick of memory drain from flash player, when i go to a certain chatroom,,my computer resources run down to ZERO , in only seconds, because of stupid flash player, i wish i could find an alternative ! 🙁
The new FLash 9 has been released. I play online games using Flash player. I am seeing major memory leaks. After like 5 minutes of playing, the fonts get a screwed up and I check the System resources, it is reaches to -10% before everything freezes. 🙁
I didnt notice this with Flash 8. I also see its called Adobe Flash , Not Macromedia(since it was bought out)
http://timotheegroleau.com/Flash/articles/scope_chain.htm
the problem seems to be more complex :
When you play a single jpeg sequence , flash use the “orginal size of the jpeg (cf image propertie) of virtual memory to display it AND don’t release it after , when displaying the next image (you believe your jpeg is 13 ko but in fact flash will use 500 ko to display it)
so , an image sequence of 100 jpeg (cf: results of 3d anim etc.) accumulate a huge memory use !!
after some try with bitmapdata class and the gskinner solution, the problem is the same, because of the bitmapdata.draw() . flash allocate the max memory for jpeg rendering and do not release it.
=> noway to dispose() the memory used :
even if the bitmap is “disposed” , the memory is not freed
if someone has a solution ?
goal :
– sequence of 500 jpegs
– playing without exploding the user ram , without video migration
PJ
Hi Grant,
I know that this is an old article but I would like to know what you use to test the memory usage of flash. You make it sound easy to see the memory usage increment and I can’t image that you use the task manager. Are there specific applications out there that you can use and if so what are they and which one do you use.
I would really like to test my apps and see how I can improve them.
Cheers
Michael
I have the exact same issue as PJ. I have a client who wants to use a Flash movie using a sequence of jpegs from a 3D rendering and it eats up to a MEG of memory, effectively killing any normal user computer memory usage. Since I have been tasked with trying to find a solution, any help would be appreciated!
I have the same problem as PJ and Carlos, I’m doing a virtual tour of my school using 3D render image in flash. And it sums up to hundreds of image and eventually flash got slower and slower eating up lots of memory, please help us in any way to solve this problems.
Hello !
I try to understand too memory management, and I come across this tool : http://www.websector.de/blog/2007/10/01/detecting-memory-leaks-in-flash-or-flex-applications-using-wsmonitor/
There some things I still don’t understand with this tool (especialy why memory usage increase when hoovering the WS Monitor buttons) but it’s a start i guess.
Max_well
Hey Grant,
This post is pretty old but useful even today. I am working on flash for years but read this article now when I ran into similar problem. I really liked the article and the way you explored the issue. I am so very impressed with you for your knowledge and attitude towards the problem others may face.
Talking about the issue I am facing, I have an application developed, which uses bitmap data a lot. It is basically a learning application for school kids and makes use of bitmap objects for letting children do drawings and fill colors. I am using the dispose method but the player never realease memory. I have next back buttons for loading pages with these bitmaps. Each time user presses next or back button memory usage increases. Even after disposing the object this memory never goes back to system.
Can you please help me sort out this problem? I have a very urgent client delivery. I hope you read this soon.
Thanks
Daljit
Hello,
I have no idea what you guys are talkig about but I came across this page when I was searching for a solution to what appears to be a problem that you have adentified as well. In summary, my issue is that after about 10 minutes of watching content with the Adobe Flash player, it seems to use ~17GB of my hard drive space and I need to reboot to get my system back to its normal operating state. Any ideas how an average user such as myself can address this problem without having to deal with code, etc?
Thanks in advance,
Dev
One more thing, I have the latest version of flash installed as of this posting (9,0,124,0)
Thanks
I’ve been doing research about this excessively high CPU usage problem (100%!) for weeks because I have also experienced it with my laptop. Just recently, I have finally found the solution. The problem is not your browser or your OS or your pc’s memory. The problem is caused by authorization for flash player.
Read the link (posted below) carefully and follow the steps accordingly. If you have already done steps 1 through 6 with your computer, you can go straight to step 7.
http://thetechangel.com/blogberry/2008/10/adobe-flash-player-10-fix-for-vista-xp/
PS: I am not the author of that link, so please thank the respective site owner if you find the procedure very helpful.
Please let me know also if the link solves your problem. I am sharing this because Adobe seems unable to provide solutions to this, and I don’t want to hear people suffer.
My blog:
http://literaryworks101.blogspot.com
http://bookofsalamat.blogspot.com
Thanks