want to re-use MemoryStream

跟風遠走 提交于 2019-12-05 05:19:36

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.

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;
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!