want to re-use MemoryStream

Jacko picture Jacko · Jan 7, 2011 · Viewed 12.2k times · Source

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;
    }

Thanks!

Answer

Aliostad picture Aliostad · Jan 7, 2011

Reusing same MemoryStream does not give you any performance benefit.

There is a reason why MemoryStream does not have a clear. Because it would be more expensive to clear it than to create a new one.

If you look at the internals of the class, you can see that it allocates a buffer, and when writing, if its buffer gets full, it allocates new buffer and copy existing bytes and then carries on. So in a way the buffer is immutable.

This can be seen here at the setting of the capacity which is called by EnsureCapacity() at the time of writing:

public virtual int Capacity
{
    get
    {
        if (!this._isOpen)
        {
            __Error.StreamIsClosed();
        }
        return (this._capacity - this._origin);
    }
    [SecuritySafeCritical]
    set
    {
        if (value < this.Length)
        {
            throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
        }
        if (!this._isOpen)
        {
            __Error.StreamIsClosed();
        }
        if (!this._expandable && (value != this.Capacity))
        {
            __Error.MemoryStreamNotExpandable();
        }
        if (this._expandable && (value != this._capacity))
        {
            if (value > 0)
            {
                byte[] dst = new byte[value];
                if (this._length > 0)
                {
                    Buffer.InternalBlockCopy(this._buffer, 0, dst, 0, this._length);
                }
                this._buffer = dst;
            }
            else
            {
                this._buffer = null;
            }
            this._capacity = value;
        }
    }
}