I'm building an Adobe AIR desktop app with Flash CS5 that makes a lot of use of bitmapdata, bytearrays and base64 strings. After a while the memory usage of the app doubles.
Is it recommended to use system.gc() to free memory at that point or is that bad practice?
Thanks.
system.gc is a debug only functionality in AIR and Flash player. I think the better thing is to recycle bitmapdata and other objects if you can to avoid gc, and if not call bitmapdata.dispose() and bitmapdata = null as soon as you are done with using them.
If you have bitmap objects of the same size at various times in your project, you can use the same instance of BitmapData to operate on them. This is similar to how ItemRenderers recycle items or how even other platforms like iOS's UITableViewController recycles/reuses UITableViewCell. Garbage collection is not panacea, it should be used when easy programmability is more important than performance.
You don't need to call system.gc as it will be called automatically on idle cycles by the Flash runtime. If you call it yourself you might end up slowing down your application for no real gain.
When you don't need a BitmapData or a ByteArray anymore, just call BitmapData.dispose() or ByteArray.clear().
Related
This is more an "implementation" of technology kind of question.
In old times, when I worked with C language, you could specify to use VGA memory or ram memory for allocation of bitmaps structures, then you could work with them a lot faster.
Now we are in 2013, I create bitmap in AS3, and it is allocated in ram (I've seen no option to use the GPU and 100% of cases im sure it is using the RAM, because it increases exactly the expected bitmap size.
¿Is there any option to use GPU memory?
Thanks
Check out the API docs for flash.display3D.Texture - there are 3 methods:
uploadCompressedTextureFromByteArray(data:ByteArray, byteArrayOffset:uint, async:Boolean = false):void
Uploads a compressed texture in Adobe Texture Format (ATF) from a ByteArray object.
uploadFromBitmapData(source:BitmapData, miplevel:uint = 0):void
Uploads a texture from a BitmapData object.
uploadFromByteArray(data:ByteArray, byteArrayOffset:uint, miplevel:uint = 0):void
Uploads a texture from a ByteArray.
So you can't allocate the memory directly in the GPU. You must upload data from a ByteArray or BitmapData, which first exists in RAM. However, to minimize CPU RAM usage, you could potentially reuse a single ByteArray or BitmapData in RAM, change its contents, and upload it many times, or release it after loading. But you can't access the contents of GPU memory directly, as far as I know.
As far as "read access", the only way to get data back from the GPU memory (again, a slow workaround) is to draw the Context3D back into a BitmapData via Context3D.drawToBitmapData... basically like a screen grab. The Starling Framework has an example of this functionality via Stage.drawToBitmapData.
Basically, the Stage3D APIs weren't setup so you can easily access the GPU memory.
You cannot allocate GPU memory manually like in other languages, but you can indeed accelerate your graphics using the GPU with different Adobe technologies.
For example if you want GPU accelerated video decoding you should be using StageVideo, or if you want to accelerate 2d or 3d graphics you could use Stage3D.
Unless you want to work in a low level fashion with Stage3D, it is recommended you use an intermediary framework.
For 2d the best solution is by far Starling. It is a solid framework endorsed by Adobe which has been used in countless commercial projects and is constantly optimised.
As for 3d take a look at Flare3D or Away3D.
Tried finding some info on this without success.
When instantiating a movieclip for later use. Is it using a lot of performance before actually adding it to stage? The question is when is flash working more. At adding to stage or instantiating to mmemory?
It depends on what is in it and what it is doing. If everything in it is graphic, it should only use CPU if it is on the Display list. If it has ActionScript code, it will depend on what that code is doing. For example, listening for ENTER_FRAME will use significant CPU cycles, as will instantiating new objects. Note that having objects coming and going from the timeline also instantiates objects.
If the object contains a lot of data (for example a BitmapData that is a 1000 x 1000 uncompressed jpg), then it will use a lot of memory.
Is flash smart enough to "hide" PIXELS that aren't on the stage, in order to decrease memory usage? Or I must do it manually, if it decreases the memory usage at all?
Flash does not render objects that aren't on the stage (as per http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e3e.html).
However I think you may be mixing up two different issues.
One issue is CPU/GPU performance - for this there is no need to worry about off-stage objects as Flash does not waste time rendering display objects that are outside the stage bounds.
The other issue is memory usage. Every object that you create takes up some memory whether or not it is visible on the screen. Flash has a garbage collector that will periodically dispose of unused objects, however "unused objects" means an object that isn't referenced by any other object so if you are having memory issues you will have to manually clean up objects by removing event listeners, nulling references etc.
There's nothing like that available to decrease memory usage. If it's visible on your monitor, it needs to be rendered by Flash and have a place in memory storing the pixel colour.
Although Flash is very fast these days, especially with hardware acceleration. So you shouldn't worry too much about performance, there's a lot of bang for your virtual buck with AS3. I'd bet all of my virtual dollars on it.
Flash will store all bitmaps, movieclips in fact all objects in memory as expected. If you have a large bitmap which is larger than the stage, it still occupies memory regardless of you only showing a portion of it.
If you have multiple bitmaps or movieclips that may move off the stage and no part of them are visible, then the only way to recover memory is to make sure the object is dereferenced and set to null.
myMovieClip = null;
Prior to setting to null you would also have to make sure that nothing else is referencing the object, for example it can't be stored in an array or have any event listeners attached to it so therefore:
myMovieClip.removeEventListener(Event.WHATEVER, eventHandler);
For bitmapdata objects you would need to call dispose first before setting to null:
myBitmapdata.dispose();
myBitmapdata = null;
This then allows the GC to recover memory when it chooses, unless you are using AIR which means you may request a gc call yourself:
System.gc();
If you are developing in Flash Builder, the best practice is to regularly profile your application and hit the button to force a gc call. You can then see which objects are persisting in memory and locate the references which are causing the memory leaks.
I saw System.gc() somewhere on the internet today and I wanted to know if it is or isn't recommended to use in a Flash CS5 project and why.
In every garbage-collected system I know of, the garbage collection machinery was designed to run in the background as an abstraction the programmer should theoretically pay no attention to. There are some special situations where forcing a collection is useful, but these usually involve interrupts (real machine interrupts, not actionscript events), testing/debugging scenarios, or some tricky latency management necessities. Odds are you will never need to call System.gc() and you can safely ignore it.
System.gc() is only available in the debugger version of Flash Player and some AIR applications. Calling it on a normal website, under a normal Flash Player will have no effect whatsoever and will silently fail.
System.gc() is designed only for testing purposes.
System.gc() is only for testing purposes. It can be handy to monitor the memory usage your application is using and call System.gc() in order to highlight the possibility of any memory leaks.
Tip: As far as I remember you have to call System.gc() twice to force it to collect immediately.
The documentation states that this method only works in a debug player.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/System.html#gc()
So, to summarise, if you're testing memory, it's quite handy, otherwise don't use it.
Here is the case: I have created a test application which simply loops to load a same url for 1000 times by using HTMLLoader class from Adobe AIR. What I found is that the memory of this app keeps rising.
So is this expected? I mean it's the same URL although it get loaded for 1000 times. Does the AVM create 1000 objects behind the scene?
It would depend on how many of the objects you keep references to, and on how many of them are available for garbage collection. It can also depend on whether or not the player decides to trigger a mark-sweep of the garbage collector (which sometimes depends on external issues like how much total memory is available from the OS).
What if you used the component and just set the url parameter to "" followed by the url again in a callLater?
Pretty sure memory wouldn't build up that way.