【问题标题】:MemoryStream exhausting内存流耗尽
【发布时间】:2017-03-23 10:22:36
【问题描述】:

我正在将一些字节写入 MemoryStream。我给它的大小是 100 MB

  using (MemoryStream Stream = new MemoryStream())
        {             
                for ( loop 1400 time)
                {                        
                  func(i, OStream, Stream, );

                }

                lock (this)
                {                       
                 Stream.WriteTo(OStream);
                }

}

func(i, OStream, Stream)
{
  loop 19 times
      get buffer;
   Stream.Write(buffer, 0, buffer.Length);
}

缓冲区是一个byte[],大小从65536到116454不等。我循环了1000次。 我在 for 循环中编写它,但我得到 OutOfMemoryException 异常。

有没有办法扩展 MemoryStream 并避免异常?

【问题讨论】:

  • 将构建模式切换到 x64
  • @middelpat anycpu 应该可以处理...
  • “我循环了 6000 次” - 在哪里?你能显示循环,也许问题就在那里。 100mb 在我看来不太像。
  • 既然你已经知道要写入更多内容,为什么还要将内存流的容量设置为 100MB?您的设置保证流必须至少扩展其存储一次(如果不是多次),这涉及将其内容复制到新数组。这(简要地)需要的内存是流当前容量的两倍多。
  • 更新问题

标签: c# memory-management


【解决方案1】:

考虑到数据量,字节数组最小为 6000*65536 字节,

即使垃圾收集器无法在两者之间进行清理,您也可能会认为最大总计为 2200 MB(字节数组为 700,初始内存流为 100,第一次扩展为 200,...)。事实上,情况可能就是这样,并且留下了“足够”的记忆。但是,它可能在连续块中不可用。

您可能面临的是内存碎片问题。大量的字节数组往往超过 85001 字节,因此它们被分配在大对象堆上。大对象堆没有被压缩,因此会产生碎片。

您可以尝试使用How to use WinDbg to track down .NET OutOfMemoryExceptions 的答案。我还发布了memory fragmentation example,以防您想与它进行比较。

可能的修复

一个快速的解决方法是编译为 x64,因为那里有更多可用内存。更清洁的方法取决于您的实际情况,并且需要优化算法,例如您可以提前计算所需结果的总大小,这样 MemoryStream 就不需要将其大小加倍。

使用单个 200 kB 字节数组并用临时数据重新填充它而不是到处创建新数组也可能很好。

如果您的最终任务是将数据写入文件,请使用 FileStream 并将其直接写入文件。

您也可以完全摆脱 MemoryStream 并将所有字节数组保存在 List<byte[]> 中。

可能还有许多其他解决方案...

【讨论】:

  • 还有一个解决方案可以添加:List<byte[]>
猜你喜欢
  • 2015-08-23
  • 2012-11-10
  • 2012-08-19
  • 2011-02-09
  • 2015-10-01
  • 2018-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多