Bri*_*edy 10 .net memory image
由于看似过早的Out of Memory异常,我们一直在仔细研究各种.NET构造的内存使用情况......特别是大型对象,这些对象倾向于分割大对象堆,导致过早的Out of Memory异常.一个有点令人惊讶的领域是.NET Image类:Bitmap和Metafile.
以下是我们认为已经学到的内容,但无法找到要验证的MS文档,因此我们希望其他人可以给予任何确认:
(1)当您从压缩的光栅文件(JPG,PNG,GIF等)创建Bitmap对象时,它会以该文件的完整分辨率为完全未压缩的像素阵列消耗内存.因此,例如,9000x3000像素的5MB JPG将扩展为9000x3000x3字节(假设为24位颜色,无alpha)或消耗81MB内存.正确?
(1a)有一些证据(见下面的2b)它也存储了原始的压缩格式......所以,在这种情况下实际上是86MB.但那还不清楚......有谁知道吗?
(2)当你创建一个Metafile对象,然后在其中绘制一个光栅文件(JPG,PNG,GIF等)时,它只消耗压缩文件的内存.因此,如果你在一个图元文件中绘制一个9000x3000像素的5MB JPG,它只会消耗大约5MB的内存.正确?
(2a)要将光栅文件绘制到Metafile对象中,唯一的方法似乎是使用该文件加载Bitmap,然后将Bitmap绘制到元文件中.有没有更好的方法不涉及临时加载巨大的位图数据(并导致相关的内存碎片)?
(2b)当您将位图绘制到图元文件时,它使用与原始压缩文件类似的压缩格式.它是通过将原始压缩文件存储在位图中来实现的吗?或者它是通过使用原始压缩设置重新压缩扩展的位图来实现的?
(3)我们最初假设大型(> 85KB)Image对象将被放置在Large Object Heap中.事实上,情况似乎并非如此.相反,每个Bitmap和每个Metafile都是Small Object Heap中的一个24字节对象,它指的是包含真实数据的Native Memory块.正确?
(3A),我们假设这样本机内存一样,它不能被压缩大对象堆......一旦大对象被放置到本机内存,它永远不会被移动,因此本机内存碎片会导致许多问题大对象堆的碎片化.真正?或者是否有更高效的底层Bitmap/Metafile数据的特殊处理?
(图3b)因此,似乎是被分开管理存储器四个独立块,并且耗尽每个可导致相同的内存例外的:小对象堆(管理对象<85KB,由GC压实),大对象堆(由GC回收,但不板结管理对象> 85KB),本机内存(非托管对象,想必不板结),以及桌面堆(其中窗口句柄和这种有限的资源管理).我是否正确记录了这四个?还有其他我们应该注意的吗?
任何人都可以提供上述任何清晰度将非常感激.如果有完整解释上述内容的好书或文章,请告诉我.(我很乐意做必要的阅读;但绝大多数书都没有那么深,所以不要告诉我任何我不知道的东西.)
谢谢!
我知道其中一些问题的答案:
(1) 是的,这就是Bitmap图像的定义。
(3) 是的,这就是Bitmap实现IDisposable接口的原因。
(3a) 这似乎令人惊讶。当您使用完 Bitmap 对象后,您是否正在对它们运行 Dispose() 方法?
(3b) 至少这四个,是的。