我有一个应用程序,它从 XML 文件(到字节数组)读取 JPEG,生成 MemoryStreams 并使用这些来实例化 BitmapImages。JPEG 文件的总大小约为 60 MB。但是,我的应用程序的内存使用量为 1.6GB(之后发生系统内存不足异常)。
我将字节数组、MemoryStreams 和(当然)BitmapImages 保留在内存中。因此,我希望得到存储在内存中的原始大小的大约三倍(也许更多),但 1.6GB 是荒谬的。
这可能是什么原因造成的?
在此先感谢您的帮助。
我有一个应用程序,它从 XML 文件(到字节数组)读取 JPEG,生成 MemoryStreams 并使用这些来实例化 BitmapImages。JPEG 文件的总大小约为 60 MB。但是,我的应用程序的内存使用量为 1.6GB(之后发生系统内存不足异常)。
我将字节数组、MemoryStreams 和(当然)BitmapImages 保留在内存中。因此,我希望得到存储在内存中的原始大小的大约三倍(也许更多),但 1.6GB 是荒谬的。
这可能是什么原因造成的?
在此先感谢您的帮助。
没那么荒谬,真的。要记住的一个好的经验法则是,JPEG 平均约为保存为 BMP 的相同图像大小的 10%。有些图像的可压缩性更高,有些则更少,JPEG 编码器的质量和压缩设置会产生显着差异,但根据我的经验,这个原则通常是成立的。
如果我们在这种情况下接受该规则为真,那么您的程序仅存储了至少 720MB 的图像数据;字节数组和 MemoryStreams 中的 60MB JPEG 数据,然后是 600MB 未压缩的 BMP 图像。此外,该程序还将自己和任何引用的第三方二进制文件加载到同一内存空间(包括引用的框架命名空间的 DLL;人们经常忘记框架不是“免费”使用的,只是因为它是“内置的” ),并记住某些集合以非常乐观的方式为自己请求内存;例如,每次达到 List 的内部最大容量时,它都会将自身调整为之前大小的两倍。字典也是如此,只是增加了维护两个内部数组结构的开销;一个用于密钥哈希,另一个用于“节点”,其中包含链接到键哈希的实际值。这种行为很容易导致处理大量对象集合的程序请求比运行时允许提供的更多内存。然后,如果这是一个图形应用程序,运行时会为每个使用图形元素的线程维护一个消息循环,并挂钩到每个图形元素(每个“窗口”,尽管该术语用词不当,因为实际上所有 GUI 元素都是“ windows”,而不仅仅是通常称为 windows 的 Form 对象)。
所有这些都可以轻松地使应用程序需要 1.6GB 的托管内存。然后,当应用程序要求增加 400MB 内存(以调整大型集合的大小)或超过 21 亿的新句柄时(.NET 即使在 64 位操作系统中也使用 32 位索引,因此运行时只能跟踪每个进程总共2 32 个不同的内存地址),运行时将注入一个 OOME。