2009-05-26 66 views
1

我的應用程序需要解壓縮包含大量Deflate壓縮塊(以及其他類型的壓縮和加密)的文件。內存分析表明,deflate流構造函數負責在其生命週期內分配大部分應用程序的內存(54.19%,其次是DeflateStream.read,12.96%,其他所有內容在2%以下)。爲了說明問題,每個文件塊通常爲4KiB(解壓縮),而DeflateStream的構造函數的分配略大於32KiB(推測爲滑動窗口)。垃圾收集器有一個現場日,因爲所有這些放氣的流幾乎沒有時間(在下一個進入之前每個都消失)!再見緩存效率。使用DeflateStream時可以使用更少的內存嗎?

我可以繼續使用DeflateStream,但我想知道是否有更好的選擇。也許有一種方法來重置流並再次使用它?

回答

3

兩點意見來支持這一行動:

  • 我想你會發現,被分配這些臨時緩衝區採取(和零)的時間量是可以忽略的下一到實際減壓所花費的時間。
  • 這些緩衝區高度瞬態的事實意味着,雖然在應用程序的整個生命週期內它可能是內存的50%,但它們都不會同時存在。請注意,這也不應該對緩存效率造成太大的影響......我想象一下,大多數這些緩衝區在緩存內存中的使用率都不會很高,因爲這些頁面很快就會過時。

總之,除非你有放氣流(無論是在速度還是絕對的內存使用),可衡量的問題,我只希望繼續使用它...更好地使用您知道不是引入另外一個解決方案這可能會有一組完全不同的難以解決的問題。

2

你有任何實際的性能問題,還是你只是擔心內存使用?

大多數對象都是短命的,所以內存管理和垃圾回收器的構建是爲了高效地處理短暫的對象。框架中的許多類都被設計爲使用一次,然後被拋棄以更短的壽命。

如果試圖掛在對象上,它們更有可能在垃圾收集中存活下來,這意味着它們將從一代堆移到另一堆。堆世代不僅僅是對象的邏輯劃分,而且對象實際上是從一個存儲區移到另一個存儲區。垃圾收集器通常遵循將堆中的所有活動對象移動到下一代的原則,然後只是清空堆,所以它是長壽命的對象,而不是短暫的對象。

由於這種設計,內存吞吐量很高,而實際的內存使用率保持較低,這是非常正常的。

+0

我正在檢查一般區域,因爲工作量稍大的性能問題,但我通過將操作移出UI線程來解決這個問題。這種記憶是我在分析問題時注意到的事情之一。感覺就像我正在分配,更重要的是,當我只需要一個32KiB緩衝區時,將所有這些緩衝區置零。 – 2009-05-27 00:45:41

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。沒有任何實際測量的利益

+0

聽起來很有趣。我不認爲暴露窗口大小是必要的或者是一個好主意。問題是我必須分配很多*和*他們很大。如果我要攻擊這個問題,我會通過允許流在一個新的子流上重置爲初始狀態來解決它。 – 2009-05-27 02:55:35

+0

窗口大小由zlib(C ilbrary)暴露。所以不是前所未有的。但是隨着我提供的抽象,我沒有將它作爲DeflateStream的一部分公開。至於回收緩衝區,您可以使用較低級別的ZlibCodec類來做到這一點。是Zlib編碼器/解碼器。 DeflateStream建立在它上面。如果你有緩衝區來解壓縮,而不是流,ZlibCodec可能就是要走的路。 – Cheeso 2009-05-27 12:59:21

相關問題