0

I would like some tips to improve the memory efficiency of my application when I serialize and deserialize an object using a memory stream.

For this example I would like to convert a class which contains a large DataTable into bytes in order to send it over TCP.

Lets assume i have the following class which i want to serialize:

[Serializable]
public class DataContainer
{
    public string TableName { get; set; }
    public DataTable DataTableData { get; set; }
}

And the following Form application:

1) Create a table and store it in a DataContainer

2) Serialize the DataContainer

3) Deserialize the DataContainer

public partial class SerialiseDesirialise : Form
{
    private DataContainer dc;
    private byte[] byteSD;

    public SerialiseDesirialise()
    {
        InitializeComponent();
        dc = new DataContainer();
    }

    private void runBtn_Click(object sender, EventArgs e)
    {
        dc.TableName = "Memory Usage Test";

        CreateTable();
        SerialiseObj();
        DeserialiseObj();
        dc = null;
        byteSD = null;
        int k = 0;
    }

    private void CreateTable()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("Column 1", typeof(string));
        dt.Columns.Add("Column 2", typeof(string));
        dt.Columns.Add("Column 3", typeof(string));

        string one = new Guid().ToString();
        string two = new Guid().ToString();
        string three = new Guid().ToString();

        for (int i = 0; i < 1000000; i++)
        {
            dt.Rows.Add(one, two, three);
        }
        dc.DataTableData = dt; 
    }

    private void SerialiseObj()
    {
        BinaryFormatter f = new BinaryFormatter();
        using (MemoryStream ms = new MemoryStream())
        {
            f.Serialize(ms, dc);
            byteSD = new byte[ms.Length];
            byteSD = ms.ToArray();
            ms.Dispose();
        }
    }

    private void DeserialiseObj()
    {
        BinaryFormatter f = new BinaryFormatter();
        using (MemoryStream ms = new MemoryStream())
        {
            ms.Write(byteSD, 0, byteSD.Length);
            ms.Position = 0;
            DataContainer _dc = f.Deserialize(ms) as DataContainer;
            _dc = null;
            ms.Dispose();
        }
    }
}

I recorded the following Process Memory values:

1) When I run the application the Process Memory = 17MB

2) When CreateTable() is completed the Process Memory = 141MB (which s understandable since its a big table)

3) When the line f.Serialize(ms, dc) is completed the Process Memory = 3GB (why? i would expect a much smaller value since the ms.Length is 338779361 bytes which is equal to 338MB)

4) After SerialiseObj() is completed the Process Memory = 1.6GB

5) Again when entering DeserialiseObj() the Process Memory reaches 3GB and drops to 1.6GB

6) Finally after the whole code is completed even if I set every variable to null the Process Memory = 1.6GB (why does not drop to 17MB?)

I was wondering if you could explain to me why the above occurs and how can I improve my application by not reaching so high Process Memory and returning to initial levels when the code is completed.

Rand Random
  • 7,300
  • 10
  • 40
  • 88
Gizazas
  • 55
  • 1
  • 8
  • 10
    `byteSD = new byte[ms.Length];` Remove this line. It makes an array you never use which will take the garbage collector time to remove. The `ms.ToArray()` on the next line will _create a new array_, not fill that one. – Nyerguds Jan 30 '18 at 12:31
  • 7
    Just a note: no need to call Dispose() inside using{} – demonplus Jan 30 '18 at 12:31
  • 1
    Instead of copying the contents of the `MemoryStream` you could directly use access the data via `ms.GetBuffer()` as long as you remember to use `ms.Length` since the buffer is slightly larger. – C.Evenhuis Jan 30 '18 at 13:34
  • Set [`dt.RemotingFormat = SerializationFormat.Binary;`](https://msdn.microsoft.com/en-us/library/system.data.datatable.remotingformat(v=vs.110).aspx) as shown in [Get `byte[]` from dataset and compress](https://stackoverflow.com/q/4685351/3744182). – dbc Jan 30 '18 at 18:36

0 Answers0