使用DeflateStream时可以使用更少的内存吗?

时间:2009-05-26 23:01:56

标签: .net memory deflatestream

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

从透视角度来看,每个文件块通常是4KiB(解压缩),而DeflateStream的构造函数分配略多于32KiB(大概是滑动窗口)。垃圾收集器有一个实地日,因为所有这些放气流几乎没有时间(每个都在下一个进入之前消失)!再见缓存效率。

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

3 个答案:

答案 0 :(得分:3)

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

  • 我认为您会发现,在实际解压缩所花费的时间之后,这些临时缓冲区的分配(和归零)所花费的时间可以忽略不计。
  • 这些缓冲区是高度瞬态的这一事实意味着虽然在应用程序的生命周期内它可能是内存的50%,但它们不会同时存在。请注意,这也不应该对缓存效率造成太大影响......我想这些缓冲区中的大部分都不会在缓存内存中大量使用它们,因为页面很快会过时。

简而言之,除非你有一个可测量的deflate流问题(速度或绝对内存使用),我只是继续使用它...更好地使用你知道的解决方案而不是引入另一个可能有的解决方案一系列难以处理的问题。

答案 1 :(得分:2)

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

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

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

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

答案 2 :(得分:2)

DotNetZip中有一个DeflateStream,实际上是.NET BCL中内置DeflateStream的替代品。 Ionic.Zlib.DeflateStream具有可调缓冲区大小。我不知道它是否会在你的场景中带来更好的内存效率,但它可能值得一试。 Here's the doc

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

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

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

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

DotNetZip是免费的,但是donations are encouraged