Jac*_*cko 7 c# memorystream reset
我的代码使用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;
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
Ali*_*tad 10
重复使用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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先你的序列化方法有一个bug:
请注意,缓冲区包含可能未使用的已分配字节.例如,如果将字符串"test"写入MemoryStream对象,则从GetBuffer返回的缓冲区长度为256而不是4,未使用252个字节.要仅获取缓冲区中的数据,请使用ToArray方法; 但是,ToArray会在内存中创建数据副本.
即数组返回大于序列化数据
对于反序列化,您可以构造一个使用传入数组的内存流,因此它不会分配内部缓冲区.但除非你有基准测试表明内存流分配确实是一个瓶颈我不会打扰.
如果您真的想要优化内存分配,则需要重用byte[]缓冲区.这尤其意味着修改api以使用数组的子部分,因此消息大小和数组大小不需要相同.
以下是可以随时更改的实现细节(自从我读到它之后可能已经发生了变化):
如果缓冲区没有在大对象堆上结束,那肯定不值得打扰.如果对象很小,它们将在下一代Gen0集合上便宜地收集.另一方面,大对象堆直接在Gen2中结束.AFAIR对象> 250kB在那里分配.
当然,重复使用缓冲区而不会缩小它们可能是内存泄漏.
| 归档时间: |
|
| 查看次数: |
11055 次 |
| 最近记录: |