MemoryStream的使用导致内存溢出异常 [英] MemoryStream usage leads to out of memory exception

查看:8933
本文介绍了MemoryStream的使用导致内存溢出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我'使用的MemoryStream多次面对的问题。

I'am facing issues when using MemoryStream multiple times.

例如:

For Each XImage As XImage In pdfDocument.Pages(pageCount).Resources.Images
   Dim imageStream As New MemoryStream()
   XImage.Save(imageStream, System.Drawing.Imaging.ImageFormat.Jpeg)

   ' some further processing

   imageStream.Close()
   imageStream.Dispose()    
Next

这件code周期,通过图像的PDF文件的网页上。该文件可能有多达CCA 500页,可以说每一页上的5张图像。这导致了成千上万的迭代。问题是,将MemoryStream不释放,这导致内存不足异常到Out。该XImage具有一般在250 KB。

This piece of code cycles through images on a page of PDF file. The file may have up to cca 500 pages, lets say 5 images on each page. It leads to thousands of iterations. The issue is that the MemoryStream is not freed and it lead to Out of Memory exceptions. The XImage has usually around 250 kB.

我使用Aspose.PDF库这里PDF工作(XImage从这个库中的类),但它并不重要。我试图做一个简单的例子,我只是创建一个新的MemoryStream和一个虚拟的位图保存到它。这导致了同样的问题。

I'm using Aspose.PDF library here to work with PDF (XImage is a class from this library), but it does not matter. I tried to make a simple example where I just create a new MemoryStream and save a dummy bitmap to it. It leads to same issues.

我也尝试过使用的FileStream,而不是MemoryStream的,但它的行为是一样的。

I also tried to use FileStream rather than MemoryStream but it behaves the same.

任何帮助AP preciated。

Any help appreciated.

感谢

吉日

推荐答案

从流的内存被释放。我像你保证。真的,就是这样。

The memory from the stream is freed. I promise you. Really, it is.

什么是不释放是的地址空间的应用程序中的前身是由内存占用。有大量的RAM提供给您的计算机,但您的特定应用程序崩溃,因为它无法找到一个地方,在它的地址表来分配了。

What is not freed is the address space in your application formerly occupied by that memory. There's plenty of ram available to your computer, but your specific application crashes because it can't find a place within it's address table to allocate any more.

原因你打的限制是将MemoryStream循环利用缓冲区因为它的增长。它使用一个字节[]内部来保存其数据,并且阵列被初始化为某一大小默认。当你写到流,如果超过数组大小的流使用一个倍增算法来分配新的阵列。信息然后从旧阵列新复制。在此之后,旧的阵列可与将被收集,但它不会被压缩的(认为:磁盘碎片整理)。其结果是在你的地址空间的孔,将不再使用。其中的MemoryStream可能会使用多个阵列,导致几个内存孔比源数据总值的地址空间可能更大。

The reason you hit the limit is that the MemoryStream recycles its buffer as it grows. It uses a byte[] internally to hold its data, and the array is initialized to a certain size by default. As you write to the stream, if you exceed the size of your array the stream uses a doubling algorithm to allocate new arrays. Information is then copied from the old array to new. After this, the old array can and will be collected, but it will not be compacted (think: defragged). The result is in holes in your address space that will no longer be used. One MemoryStream might use several arrays, resulting in several memory holes worth a total address space potentially much larger than the source data.

AFAIK,有没有办法在这个时候强制垃圾收集压缩你的内存地址空间。因此,解决的办法是分配一个大的块,将处理您的最大图像,然后一遍又一遍地重复使用同一个块,这样你就不会结束与无法达到的内存地址。

AFAIK, there is no way at this time to force the garbage collector to compact your memory address space. The solution therefore is to allocate a big block that will handle your largest image, and then reuse that same block over and over, so that you don't end up with memory addresses that can't be reached.

有关此code,这意味着创造的MemoryStream的循环之外,并传递一个整数的构造函数,以便它被初始化为字节合理数量。你会发现这个也给你一个不错的性能提升,为您的应用程序突然不再花时间频繁地从一个字节数组复制到另一个数据,这意味着这是更好的选择,即使你可以压缩你的地址表:

For this code, that means creating the memorystream outside of the loop, and passing an integer to the constructor so that it is initialized to a reasonable number of bytes. You'll find this also gives you a nice performance boost, as your application suddenly no longer spends time frequently copying data from one byte array to another, meaning this is the better option even if you could compact your address table:

Using imageStream As New MemoryStream(307200) 'start at 300K... gives you some breathing room for larger images
    For Each XImage As XImage In pdfDocument.Pages(pageCount).Resources.Images

       'reset the stream, but keep using the same memory
       imageStream.Seek(0, SeekOrigin.Begin)
       imageStream.SetLength(0)

       XImage.Save(imageStream, System.Drawing.Imaging.ImageFormat.Jpeg)

       ' some further processing

    Next
End Using

这篇关于MemoryStream的使用导致内存溢出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆