2010-05-11 65 views
1

我的.NET應用程序確實有些沉重串裝/操作和不幸內存消耗不斷上升和上升,並在其與探查我看到很多未發行的字符串實例看時。現在,在某個時間點或另一個時間點,我確實需要所有對象都有這些字符串字段,但一旦完成,我就可以擺脫它的一半和我Dispose()並將實例設置爲null,但垃圾收集器不會選擇它..他們仍然在內存中(即使在處理後的半小時等)。應用程序泄漏字符串?

現在我怎麼得到正確擺脫不需要的字符串/對象實例才能釋放它們?

他們無處了(據我所知)提及,但如aspose的記憶分析器說他們到gc根的距離是'3'?

更新:原字符串從互操作實例來。是否有可能導致泄漏?

如..分配

myClass.StringProperty = interopInstance.Description.Text; 

..沒有我.StringProperty還是要那一個互操作的參考,因此「泄漏」 /保持interopInstance未收&無法正常發佈/取消封送的?

+0

我對Aspose的內存分析器不熟悉,但是如果它與GC的根有一定的距離,那麼在我看來它被引用了。 Aspose不允許你看到它被引用的地方嗎? – Steven 2010-05-11 11:27:19

回答

3

時仍然會使用含有該字段的類中的私有字段設置爲null可能是有用的。它將允許收集被引用的對象。但是,當該私有字段本身的實例未被引用時,它所引用的對象也是如此。換句話說,將對象上的私有字段置空即可,這將毫無用處。

我想你沒有一個應用程序泄漏。也許你正在創建存儲在大對象堆(LOH)中的字符串。對象在大於或等於85000字節(42492個字符或更多)時存儲在LOH中。只有在完整的垃圾收集(第2代)發生時才收集LOH。因此,由於你似乎沒有任何OutOfMemoryExceptions,我不認爲有泄漏。您的應用程序不會耗盡內存,並且GC不會收集Gen2。

您可以通過致電GC.Collect()進行檢查。這將刪除所有未使用的大對象。


因此,雖然應用程序中可能沒有泄漏,但內存佔用可能不理想。特別是在編寫桌面應用程序時,它不是唯一需要內存的應用程序。除此之外,大量內存也可能導致性能問題,因爲GC必須更頻繁地運行。

也許有可能以一種使用更少內存的方式重構代碼。例如使用StringBuilder對象(如果您還沒有這樣做)。或者甚至可能緩存池中的StringBuilder對象,並重新使用它們而不是創建新對象。特別是在使用從池中獲取的實例時設置Capacity屬性。這可能特別有用,因爲LOH易於分散,這可能會導致發生OutOfMemoryExceptions。這在32位系統上只是一個問題,因爲64位系統具有幾乎無限的虛擬地址空間。 64bit在未來幾年會越來越主流,我相信微軟並沒有投入資金來解決CLR的32位版本的這個問題,因此。

更新 在互操作的情況下,字符串是序列化和反序列化。一個字符串作爲字節數組發送,因此通常不會改變引用。但是,每次從interop獲取一個字符串時,都會創建一個新的字節數組,並在.NET中將byte []複製到一個字符串中。這將使所使用的內存量增加一倍。

+1

但是不要經常調用GC.Collect(),這對性能來說是相當糟糕的。 – 2010-05-11 10:30:46

+0

@Rafal:當然可以。我不是說我應該在生產代碼中使用它。用它來測試內存是否可收集。 – Steven 2010-05-11 10:34:05

+0

哦,我確實得到了SystemOutOfMemoryExceptions ..在一個示例運行中,我擁有大約1200個我的類的實例,其中包括其他小字符串屬性中的一個「大」字符......這意味着我的類的每個實例通常有幾個100kbyte,有時幾個兆字節的字符串'數據'在其中。 (我不幸需要)。 – 2010-05-11 10:37:58

1

只是在這個平臺上,但你串聯了很多字符串?如果是這樣,你使用'+'運算符來做到這一點?一個字符串是不可變的,這意味着您可以在每次處理時在內存中創建一個新的字符串對象。

如果你串聯字符串,你應該考慮使用一個StringBuilder對象(如果你還沒有這樣做)或者甚至是String.Concat()方法。這可能是問題,特別是如果你在任何一點連接循環中的字符串。

0

我一直致力於在許多終端之間傳輸數據的系統。這些終端生成文本數據(XML),然後壓縮並傳輸到其他終端。最初,我們遇到了與使用越來越多Ram的應用程序完全相同的問題,並最終耗盡內存。連接到它的終端越多,其耗盡速度就越快。

該系統的性能不是最重要的功能,但長期正常運行時間。

用輪廓儀找出我們的記憶在哪裏消失之後,我們發現我們的弦最後出現在LOH中,如果其中有任何實質性的話。

我知道這是有爭議的,許多人說不要強迫GC.Collect,但我也發現其他網站,例如Rico Mariani,說如果你有特定的需求,你確定你的對象最終在蕙,然後繼續前進做到這一點,只要記住GC.Collect會影響性能。

好消息是,一旦我們將此添加到程序的字符串處理區域中,我們就會繼續關注應用程序整個生命週期中的相同的RAM使用情況,並且我們運行的一些系統具有正常運行時間> 60天。