Main Site Documentation

Memory consumtion and FileStream


#1

Hi all,

I don’t understand well to the memory management of .NETMF so I would like to ask you if you can explain it to me. I have the following method:

static public void DoCreateQueue()
{
    Debug.Print("DoCreateQueue IN:  " + Debug.GC(true).ToString());
    string str = "timestamp=" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    str += "&tRoom=" + Devices.GetValue("tRoom");
    str += "&iRoom=" + Devices.GetValue("iRoom");
    str += "&mMemory=" + Debug.GC(false).ToString("F1");

    byte[] data = Encoding.UTF8.GetBytes(str + "\r\n");
    using (FileStream FileHandle = new FileStream(@ "\SD\tasks\file.txt", FileMode.Append))
    {
        FileHandle.Write(data, 0, data.Length);
        FileHandle.Close();
        FileHandle.Dispose();
    }
    data = null;
    str = null;
    Debug.Print("DoCreateQueue OUT: " + Debug.GC(true).ToString());
}

As you can see I print available memory in the beginning and also at the end. Method Devices.GetValue just read static value from class Devices. I force to close and dispose everything I created. I don’t use any global variable. But still I have about 2.2kB difference in free memory. The memory used in allocation of FileStream is never released. Even when I force garbage collector by calling Debug.GC(true). In next call of this method the memory in beginning and in the end are same. But the first run takes about 2.2kB and never release it. And it is similar with other objects in different methods (for example StreamReader). So it is very easy to end up with run out of memory. I thought when I dispose all local variables I should free memory I used. I don’t want to drag all used memory all the time. I want use memory, free this used memory and use it for another object.

When I turn on GC messages I see differences in STRING, CLASS and BINARY_BLOB_HEAD. The largest difference is in BINARY_BLOB_HEAD - 2028 vs. 3996 bytes. Do you know what is this? And why is there such difference?

It is really hard to handle memory management with such behavior. Or am I doing something wrong? May be I don’t understand the memory management of CSharp well.


#2

@ Hall - About how much data are you writing to the file?


#3

Everything what is in “str”. GetValue returns string like ##.#. So I guess usually 65 bytes.


#4

@ Hall - You can put Debug.Print(Debug.GC(true).ToString()); in between every line of the program to see where the memory allocation occurs.


#5

Still no answer to this interesting question! :frowning:


#6

Thanks John for reply. I added these Debug.Print:

static public void DoCreateQueue()
{
    Debug.Print("DoCreateQueue IN:  " + Debug.GC(true).ToString());
                        
    string str = "timestamp=" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    str += "&tRoom=" + Devices.GetValue("tRoom");
    str += "&iRoom=" + Devices.GetValue("iRoom");
    str += "&mMemory=" + Debug.GC(false).ToString("F1");

    byte[] data = Encoding.UTF8.GetBytes(str + "\r\n");
    Debug.Print("Before FileStream allocation:  " + Debug.GC(true).ToString());
    using (FileStream FileHandle = new FileStream(@ "\SD\tasks\file.txt", FileMode.Append))
    {
        Debug.Print("After FileStream allocation:  " + Debug.GC(true).ToString());
        FileHandle.Write(data, 0, data.Length);
        Debug.Print("After Write:  " + Debug.GC(true).ToString());
        FileHandle.Close();
        FileHandle.Dispose();
        Debug.Print("After Dispose:  " + Debug.GC(true).ToString());
    }
    Debug.Print("After using:  " + Debug.GC(true).ToString());
    data = null;
    str = null;
    Debug.Print("DoCreateQueue OUT: " + Debug.GC(true).ToString());
}

And this is the output:

1st round:
DoCreateQueue IN: 26736
Before FileStream allocation: 26280
After FileStream allocation: 20712
After Write: 20712
After Dispose: 21912
After using: 21912
DoCreateQueue OUT: 22092

2nd round:
DoCreateQueue IN: 22236
Before FileStream allocation: 22056
After FileStream allocation: 20712
After Write: 20712
After Dispose: 21912
After using: 21912
DoCreateQueue OUT: 22092

3rd round:
DoCreateQueue IN: 22236
Before FileStream allocation: 22056
After FileStream allocation: 20712
After Write: 20712
After Dispose: 21912
After using: 21912
DoCreateQueue OUT: 22092

I don’t understand the difference between first round and all others. I don’t know why there is more free memory in the beginning than at the end. I released, closed and disposed everything. But let’s say the memory is released when I leave the method - see the same pattern in 2nd and 3rd round. But stil I lost almost 4.5kB if you compare beginning of 1st round and all others.

Can anybody give me the explanation?

I also found out very interesting behavior I didn’t know before. When I set breakpoint and go line after line free memory is much lower. In 3rd round I usually end up with 16kB free memory instead of fixed 22092Bytes. So debugging cost me almost 6kB. Interesting…


#7

At the end of each round you have the same amount of free memory. This is a good sign I would say.
The reason that some of the RAM is not freed after the 1st round might be, that internal resources and buffers are created on 1st usage, which are not freed to improve performance and are reused when used again.