我有一個C#服務,它監聽隊列中的XML消息,接收它們,使用XSLT處理它們並將它們寫入數據庫。 它每天處理約60K條消息,每條約1Mb。內存閒置時會降到100MB,這真的很不錯。 但是最近我開始處理大小爲12 MB的消息。它確實打擊了內存,即使閒置它也有大約500MB的內存。任何建議,爲什麼這可能是一個問題?我不認爲存在內存泄漏,因爲在處理這麼多的消息(1K的60K消息)後會出現內存泄漏。.NET中的內存問題
回答
看起來非常好。你爲什麼認爲這是一個問題?
垃圾收集器最終會釋放未使用的內存,但這並不意味着一旦您的服務空閒就會發生這種情況。
雷蒙德陳寫了一篇很好的文章解釋了垃圾收集的基本思想:
但是 - 但是這是純粹的投機,在你的問題中給出的信息 - 有可能是與XSLT中擴展方法相關的內存泄漏。每次新的XML文檔轉換時,擴展方法可能會導致出現問題,以防重新編譯樣式表。修復很簡單:編譯後,緩存樣式表。
很難說什麼可能是問題。調查記憶問題時,我已經成功使用Ants Memory Profiler。
與此想法相反我不認爲有內存泄漏;我會profile的內存。
你對內存使用了什麼措施?有很多可能的措施,沒有一個真正意味着「使用過的記憶」。藉助虛擬內存,共享圖像等等,事情並不簡單。
處於空閒狀態,即使它擁有大約500MB
大多數進程的內存(我認爲這包括.NET)不會釋放內存回一次分配過程中的OS。但是如果它沒有被使用,它將從物理內存中分頁,從而允許其他進程使用它。
開始在尺寸
處理的12 MB的消息如果XML文檔擴展成一個對象模型(例如XmlDocument
)它需要更多的存儲器(大量的鏈接到其他節點)。要麼查看不同的模型(XDocument
和XPathDocument
都較輕),或者更好地,使用XmlReader
來處理XML,因此從未擁有完全擴展的對象模型。
SIR!放下任務經理和行走。認真。 .NET中的內存管理並未針對最小尺寸進行調整。它調整效率。它將保持內存而不是釋放回系統。抵制保姆的誘惑,除非存在實際問題(OOM例外,系統問題)。
首先,向系統中添加一些東西,以便您可以手動調用垃圾回收來進行調查。除非供應不足,否則CLR不一定會將內存返回給操作系統。當系統處於靜止狀態時,您應該使用此機制手動調用垃圾回收,以便您可以查看內存是否回退。 (你應該調用GC.Collect(2)
兩次,以確保與終結的對象實際上是收集並不僅僅是完成。)
如果內存下降到一個完整的GC後的靜態水平,那麼你沒有一個問題:僅僅是.NET是不積極主動去分配內存。
如果內存不下來,那麼你有某種泄漏。由於你的信息很大,這意味着它們的文本表示很可能以大對象堆(LOH)結束。這個特殊的堆沒有壓縮,這意味着比其他堆更容易泄漏這個內存。
要注意的一件事是字符串實習:如果您手動實習字符串,可能會導致LOH分段。
字符串文字的編譯器實習會導致相同的碎片嗎? – 2010-09-24 13:13:14
@Matt Briggs:不,編譯器實際上並沒有執行任何實際操作,而是所有字符串文字都是以這樣的方式編譯的,即程序啓動時只會創建一個字符串對象。 – 2010-09-24 13:21:16
我會檢查你的事件處理程序。如果在完成時不小心分離那些,那麼創建不會被GC收集的對象引用似乎很容易。
我不知道這是最好的做法(因爲開始和取消事件處理的責任應歸於訂閱者),但我已經走過了實現IDisposable並通過顯式委託字段實例創建事件的路線。在處置時,該字段可以設置爲空,從而有效地分離所有訂閱。
是這樣的:
public class Publisher
: IDisposable
{
private EventHandler _somethingHappened;
public event EventHandler SomethingHappened
{
add { _somethingHappened += value; }
remove { _somethingHappened -= value; }
}
protected void OnSomethingHappened(object sender, EventArgs e)
{
if (_somethingHappened != null)
_somethingHappened(sender, e);
}
public void Dispose()
{
_somethingHappened = null;
}
}
除非是(我不知道你有多大的控制了發佈者),你可能需要小心拆下你的用戶不需要的處理程序:
public class Subscriber
: IDisposable
{
private Publisher _publisher;
public Publisher Publisher
{
get { return _publisher; }
set {
// Detach from the old reference
DetachEvents(_publisher);
_publisher = value;
// Attach to the new
AttachEvents(_publisher);
}
}
private void DetachEvents(Publisher publisher)
{
if (publisher != null)
{
publisher.SomethingHappened -= new EventHandler(publisher_SomethingHappened);
}
}
private void AttachEvents(Publisher publisher)
{
if (publisher != null)
{
publisher.SomethingHappened += new EventHandler(publisher_SomethingHappened);
}
}
void publisher_SomethingHappened(object sender, EventArgs e)
{
// DO STUFF
}
public void Dispose()
{
// Detach from reference
DetachEvents(Publisher);
}
}
- 1. .NET內存消耗問題
- 2. .net內存泄漏問題
- 3. 內存泄漏問題.net
- 4. .NET中內存泄漏的問題
- 5. C++中的內存問題
- 6. Android中的內存問題
- 7. Java中的內存問題
- 8. ARC中的內存問題
- 9. C中內存的問題#
- 10. JMImageCache中的內存問題
- 11. SDWebImage中的內存問題
- 12. iPhone中的內存問題
- 13. Android中的內存問題
- 14. Visual Studio 2010中的內存不足問題Visual Basic .NET 4.0
- 15. .Net 3.5中BinaryFormatter類的內存泄漏問題
- 16. 內存問題?
- 17. 內存問題
- 18. 內存問題
- 19. 從內存中訪問.net程序
- 20. 圖片問題的iPad - 內存問題
- 21. 在.net Winforms中保存圖像問題
- 22. ValueAnimator內存問題
- 23. Apache內存問題
- 24. ScrollView內存問題
- 25. Android內存問題
- 26. FragmentStatePagerAdapter內存問題
- 27. 內存問題iphone
- 28. iphone內存問題
- 29. UIImageView - 內存問題
- 30. IntelliJ內存問題
當服務空閒併發生垃圾收集時,我期望內存完全停止運行。而且,如果這些巨大的消息中有很多來自服務,它確實會拋出內存異常。 – koumides 2010-09-24 12:47:08
@koumides:一旦你的服務空閒,你的內存將不會被釋放,垃圾收集器會根據所做的分配在最佳時間執行內存釋放。 – James 2010-09-24 12:52:22
你如何測量內存使用量?任務管理器並不是最好的方式...像CLR Profiler這樣的分析器可以讓您更好地瞭解有多少內存正在被分配和使用。 – 2010-09-24 12:53:35