1

我的应用程序需要解压缩包含大量 Deflate 压缩块(以及其他类型的压缩和加密)的文件。内存分析显示,deflate 流构造函数负责在其生命周期内分配应用程序的大部分内存(54.19%,其次是 DeflateStream.read,占 12.96%,其他所有内存都低于 2%)。

换个角度来看,每个文件块通常是 4KiB(解压后),而 DeflateStream 的构造函数分配的空间略大于 32KiB(大概是用于滑动窗口)。垃圾收集器有一个现场日,因为所有这些放气流几乎不会持续任何时间(每个都在下一个到来之前消失)!再见缓存效率。

我可以继续使用 DeflateStream,但我想知道是否有更好的选择。也许是一种重置流并再次使用它的方法?

4

3 回答 3

3

两条评论没有任何实际测量的好处来支持这一点:

  • 我想你会发现这些临时缓冲区的分配(和归零)所花费的时间与实际解压缩所花费的时间相比可以忽略不计。
  • 这些缓冲区是高度瞬态的,这意味着尽管在应用程序的生命周期中它可能占内存的 50%,但它们都不会同时存在。请注意,这也不应该对缓存效率造成太大影响……我想这些缓冲区中的大多数在缓存内存中的使用不会超过它们的使用时间,因为页面会很快过时。

简而言之,除非您对 deflate 流有可衡量的问题(无论是在速度还是在绝对内存使用方面),我都会继续使用它......最好使用您知道的解决方案,而不是引入另一个可能有完全不同的解决方案一系列更难处理的问题。

于 2009-05-27T02:45:02.103 回答
2

您是否有任何实际的性能问题,或者您只是担心内存使用情况?

大多数对象都是短命的,因此内存管理和垃圾收集器旨在有效地处理短命的对象。框架中的许多类被设计为使用一次然后丢弃以更短的寿命。

如果您尝试挂在对象上,它们更有可能在垃圾收集中幸存下来,这意味着它们将从一个堆代移到另一代。堆生成不仅仅是对象的逻辑划分,而是对象实际上从一个内存区域移动到另一个内存区域。垃圾收集器的工作原理通常是将堆中的所有活动对象移动到下一代,然后清空堆,因此成本高的是长期存在的对象,而不是短期存在的对象。

由于这种设计,内存吞吐量较高而实际内存使用量保持较低是很正常的。

于 2009-05-27T00:02:43.197 回答
2

DotNetZip 中有一个 DeflateStream 有效地替代了 .NET BCL 中的内置 DeflateStream。Ionic.Zlib.DeflateStream 有一个可调的缓冲区大小。我不知道它是否会在您的场景中带来更好的内存效率,但它可能值得一试。 这是文档

我没有测试解压,而是压缩。在我的测试中,对于我压缩的数据子集,我发现将缓冲区大小扩展到 4k 以上的回报有限。另一方面,即使缓冲区是 1024 字节,您仍然可以获得准确、正确的压缩,尽管它的效果较差。我想你会在减压中看到类似的结果。

在任何一种情况下,都不能直接从公共界面设置窗口大小。但是,它是开源的,您可以根据需要轻松修改默认的 Wwindow 大小。此外,如果您认为它很有价值,我可以请求将窗口大小公开为 DeflateStream 上的可设置参数。我没有暴露它,因为没有人要求它。然而?

你说你也有其他压缩。如果您使用 Zlib 或 GZip,DotNetZip 包中也有 ZlibStream 和 GZipStream。

如果你想做 Zip 文件,你需要完整的 DotNetZip 库(Ionic.Zip.dll,大约 400k)。如果你只是在做 {Deflate, Zlib, GZip}Stream,那么就有一个 Ionic.Zlib.dll,大约 90k。

DotNetZip 是免费的,但鼓励捐款

于 2009-05-27T02:16:51.040 回答