I have this blank project, just to check out System.totalMemory variable. As far as I can see, i get this values:
3076
3092
3096
3088
3092
3096
3100
3104
3108
3112
3117
3121
3125
3129
3133
3137
3141
3145
3149
...
And so on
I had no Flash open, no Internet Browser, no other instance of flash.
The project is blank, only one static text, and one dynamic text, called 'memory'. One *.as file, that contains this code:
package{
import flash.display.Sprite;
import flash.events.Event;
import flash.system.System;
import flash.text.TextField;
public class Test extends Sprite {
public function Test() {
this.addEventListener(Event.ENTER_FRAME,Loop);
}
public function Loop(e:Event) {
memory.text = String(System.totalMemory);
}
}
}
These are my Publish Settings.
I tested in the Debug and Published *.swf, same results.
I have no clue on this one, so please help.
Maybe this is obvious, but remember that System.totalMemory gives you the amount of memory used by Flash Player (static). If you have other Flash application opened, this might explain why your memory is increasing.
I think you've got a couple of things wrong.
First, your traces display totalMemory truncating the last 3 digits (since you're not doing it in the code, I assume it's because of the TextField width). It grows like this: 3076, 3092, 3096, etc. These are (roughly) Kilobytes, not bytes. Then you comment: "totalMemory after 2 hours: 3887104. My god". Now, if by 3,887,104 you mean 3,887,104 Kb, that would be about 3.8 Gb. I doubt that's the case, so let's assume you mean 3,887,104 bytes. That's about 3,800 Kb or 3.8 Mb. Not that much memory, actually, and more importantly, not so far from your initial 3,076 Kb.
I think this actually mislead another poster to think the player was incrementing memory usage by 4 bytes, when it actually increments by 4,096 bytes, or 4 Kb.
Second, even though the code is very simple, it does consume memory. For starters, each time the ENTER_FRAME event is dispatched, an Event object, which in turn contains references to other objects, strings, etc, is created. That takes memory. Then you are converting a number to a string implicitly (by printing totalMemory). That takes memory, too, whether you make an explicit conversion or not (the same applies if you make a trace instead of using a text field). On top of that, there's for sure other stuff going on that is not evident from an "actionscript point of view".
Now, I think part of the problem is that you're just tracing the current totalMemory. Looking at it, it seems as though it's growing, slowly but steadily, all the time. And that is true, but you're probably missing is that, at a slower pace, the GC kicks in and releases a lot of the memory that has been accumulating.
This is more evident if you modify the code to calculate a few things.
I'm using chunks of 4096 bytes as the unit (That's why I'm doing System.totalMemory >> 12. Just a fancy way to say System.totalMemory / 4096). I think it's more manageable and anyway totalMemory always return multiples of 4096 byes or 4kb. You can read more about Flash's GC here: https://developer.mozilla.org/en/MMgc. That part of the player is open source, and you can even read the sources if you're so inclined.
A brief explanation on what the code traces:
Now, let's look at some "snapshots" taken using this code.
This is a early snapshot, taken when the swf's been running for 3 seconds. Just note that current reads 760.
After about 10 minutes:
A couple of things to note:
Now, let the swf run some more time. After running for 50 minutes, the snapshot looks like this:
At this point you might think there's a leak. Note how the current memory is 931, versus the initial 760.
But look what happens at 3124 sec, ~52 minutes:
Before the GC kicked in, the peak grew to 962. But after that, current went down to 767, again, very close to the initial 760.
So, to wrap it up, the fact that memory usage grows up does not necessarily mean there's a leak. You just have to deal with the fact that the player is garbage collected, and that process is non deterministic. Memory will eventualy be reclaimed at some point (unless you do have a leak in your code, of course). You cannot determine when will this happen. It will happen when the player determines it's necessary. And in general, the player knows better.
That said, I think it's important to pay attention to possible leaks in your code. But just tracing System.totalMemory is not going to help you determine that. If you can, use a tool such as Flex Builder's memory profiler, which is not perfect but gives you much more useful info. And be careful when adding listeners to the stage and when using timers, the biggest culprits of memory leaks in the flash player.
As the text in the textfield changes, Flash will have to load different characters in to memory to display them. This could explain the few hundred bytes of increase you are getting.
Left alone, how much bigger does the footprint get?
UPDATE: Having thought about it, I think it is to do with the temporary bitmap graphics which are being created for Flash to render text... although you wouldn't expect that with trace... although trace must do some internal things too...
Have you thought of running it in FlexBuilder? That has a profiling tool which might tell you where your memory is going.
You may want to check to see which version of the Flash player you are running. If you have the IDE installed there is a decent chance you are running in the debug version of the player - which tends to not free up memory nearly as often (if at all) compared to the normal player.
If you are running in the debug player you can force a gc sweep - System.gc();
As far as I can tell, on each loop, the call to System.totalMemory returns a uint representing the amount of memory in bytes current in use by Flash. The uint returned by the call to System.totalMemory is stored in memory (i.e., your RAM, not the textField that you have labeled "memory"). The memory.text reference is then updated to point to the space in memory occupied by the uint. The old uint is still in memory, but there's no reference to it. Uints are 32 bits (4 bytes) of data, so you are seeing your memory footprint increase by 4 bytes every time. Once the garbage collector runs, the space in memory occupied by the now derefrenced uints should get freed and you should see the memory drop.
However, when I run your sample code, I get nothing like that. It goes up and down, it doesn't go consistently up like yours, but I'm on OS X so it's a different player.