简体   繁体   中英

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

Thanks!

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

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.

ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM