Search code examples
c#resetmemorystream

How to re-use MemoryStream


My code uses MemoryStream to serialize/deserialize objects to/from the network. I would like to re-use a single MemoryStream in my class, rather than create a new one each time I need to send something over the wire.

Does anyone know how to do this?

Code snippet:

// Serialize object to buffer
public byte[] Serialize(object value)
{
    if (value == null)
        return null;
    MemoryStream _memoryStream = new MemoryStream();

    _memoryStream.Seek(0, 0);
    _bf.Serialize(_memoryStream, value);
    return _memoryStream.GetBuffer();
}

// Deserialize buffer to object
public object Deserialize(byte[] someBytes)
{         
    if (someBytes == null)
        return null;
    MemoryStream _memoryStream = new MemoryStream();
    _memoryStream.Write(someBytes, 0, someBytes.Length);
    _memoryStream.Seek(0, 0);
    var de = _bf.Deserialize(_memoryStream);
    return de;
}

Solution

  • First of all your serialize method has a bug:

    Note that the buffer contains allocated bytes which might be unused. For example, if the string "test" is written into the MemoryStream object, the length of the buffer returned from GetBuffer is 256, not 4, with 252 bytes unused. To obtain only the data in the buffer, use the ToArray method; however, ToArray creates a copy of the data in memory.

    i.e. the array returns is larger than the serialized data

    For deserializing you can construct a memory stream which uses the passed in array, so it won't allocate internal buffers. But unless you have benchmarks which show that memory stream allocation is really a bottleneck I wouldn't bother.

    If you really want to optimize your memory allocations you'll need to reuse the byte[] buffers. This in particular means modifying the api to work with subsections of arrays so the message size and array size don't need to be identical.

    The following are implementation details which can change at any time(and might already have changed since I read about it):
    It's surely not worth bothering if the buffers don't end up on the large object heap. If the objects are small they'll be cheaply collected on the next Gen0 collection. The large object heap on the other hand directly ends up in Gen2. AFAIR objects >250kB are allocated there.

    And of course reusing the buffers without ever shrinking them can be a memory leak.