我将二进制数据格式写入包含序列化对象图的文件。为了更好地适应错误(并且能够调试问题),我正在考虑对流中的每个对象进行长度前缀。我目前正在使用C#和BinaryWriter,但这是一个普遍的问题。
每个对象的大小在完全序列化之前是不可知的,所以能够 写长度前缀有很多策略:
使用具有足够空间的写缓冲区进行随机访问,并在序列化对象后将长度插入正确的位置。
将每个对象写入自己的MemoryStream,然后将缓冲区的长度和缓冲区内容写入主流。
为第一遍中的所有对象写一个零长度,记住文件中所有对象大小的位置(对象大小的表),并填写所有大小的第二遍。
...
总尺寸(以及第一个/最外面的物体的尺寸)通常约为1mb,但可以大到50-100mb。我担心的是该过程的性能和内存使用情况。
哪种策略最有效?
答案 0 :(得分:0)
哪种策略最有效?
确定这一点的唯一方法是衡量。
我的第一直觉是使用#2,但知道这可能会给GC增加压力(或者如果工作流超过80Kb则会碎片化为大对象堆)。然而,#3听起来很有趣,假设跟踪这些位置的复杂性不会影响可维护性。
最后,您需要使用数据进行衡量,并考虑除非您遇到异常情况,否则性能将受网络或存储性能的控制,而不是内存中的处理。
答案 1 :(得分:0)
100MB仅占“小型”服务器(或标准台式计算机)内存的2.5%。我将序列化为内存(例如带有BinaryWriter的byte []数组/ MemoryStream),然后在完成后将其刷新到磁盘。
这也可以让您的代码保持干净,紧凑,易于管理 - 让您免于数小时撕裂头发并在大块地方来回寻找:)
希望这有帮助!
答案 2 :(得分:0)
如果您控制格式,则可以累积对象大小列表并在文件末尾附加目录。但是,不要忘记在.NET世界中,您的写缓冲区在实际传输到磁盘之前会被复制多次。因此,通过避免(比方说)额外的MemoryStream
而获得的任何收益都不会提高整体效率。