我的代码使用MemoryStream将对象序列化/反序列化到网络或从网络反序列化。我想在我的课程中重复使用单个MemoryStream,而不是每次需要时都创建一个新的MemoryStream 通过电线发送东西。
有谁知道怎么做?
代码段:
// 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;
}
谢谢!
答案 0 :(得分:11)
重复使用相同的MemoryStream
不会给您带来任何性能优势。
MemoryStream
没有明确的原因。因为清除它比创建新的更昂贵。
如果查看类的内部,可以看到它分配了一个缓冲区,在写入时,如果它的缓冲区已满,它会分配新的缓冲区并复制现有的字节,然后继续。 所以在某种程度上缓冲区是不可变的。
在此处可以看到EnsureCapacity()
在撰写本文时调用的容量设置:
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;
}
}
}
答案 1 :(得分:8)
首先,你的序列化方法有一个错误:
请注意,缓冲区包含可能未使用的已分配字节。例如,如果将字符串“test”写入MemoryStream对象,则从GetBuffer返回的缓冲区长度为256而不是4,未使用252个字节。要仅获取缓冲区中的数据,请使用ToArray方法;但是,ToArray会在内存中创建数据副本。
即。数组返回大于序列化数据
对于反序列化,您可以构造一个使用传入数组的内存流,因此它不会分配内部缓冲区。但除非你有基准测试表明内存流分配确实是一个瓶颈,否则我不会打扰。
如果您真的想要优化内存分配,则需要重用byte[]
个缓冲区。这尤其意味着修改api以使用数组的子部分,因此消息大小和数组大小不需要相同。
以下是可随时更改的实施细节(自我阅读以来可能已经改变):
如果缓冲区没有在大对象堆上结束,那肯定不值得打扰。如果对象很小,它们将在下一代Gen0集合上便宜地收集。另一方面,大对象堆直接在Gen2中结束。那里分配了> 250kB的AFAIR对象。
当然,重复使用缓冲区而不会缩小它们可能会造成内存泄漏。