簡體   English   中英

了解內存性能計數器

[英]Understanding Memory Performance Counters

[更新 - 2010年9月30日]

由於我對這個及相關主題進行了很多研究,我會寫出我從我的經驗和建議中收集的任何提示,這些提示在這里給出了答案 -

1)使用內存分析器(嘗試CLR Profiler,開始)並找到消耗max mem並對其進行微調的例程,如重用大數組,嘗試將對象的引用保持在最小。

2)如果可能,分配小對象(對於.NET 2.0少於85k)並使用內存池,如果可以避免垃圾收集器的高CPU使用率。

3)如果增加對象的引用,則負責將它們取消引用相同的次數。 你會安心,代碼可能會更好。

4)如果沒有任何作用且您仍然無能為力,請使用消除方法(注釋/跳過代碼)來找出消耗最多內存的內容。

在代碼中使用內存性能計數器也可能對您有所幫助。

希望這些幫助!


[原始問題]

嗨!

我在C#工作,我的問題是內存不足異常。

我在這里讀了一篇關於LOH的優秀文章 - > http://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/

太棒了!

並且, http://dotnetdebug.ne​​t/2005/06/30/perfmon-your-debugging-buddy/

我的問題:

我在企業級桌面應用程序中遇到內存不足問題。 我試着閱讀並理解有關內存分析和性能計數器的內容(嘗試過WinDBG! - 一點點)但我仍然對基本內容毫無頭緒。

我嘗試使用CLR分析器來分析內存使用情況。 它有助於:

  1. 告訴我誰分配了大量的內存

  2. 什么數據類型使用最大內存

但是,CLR Profiler和性能計數器(因為它們共享相同的數據)都無法解釋:

  1. 每次運行應用程序后收集的數字 - 如何理解是否有任何改進?!?!

  2. 如何比較每次運行后的性能數據 - 特定計數器的優先級是低還是高?


我需要的:

我正在尋找以下提示:

  1. 如何釋放(是,正確) 托管數據類型對象(如數組,大字符串) - 但如果可能的話,不要通過進行GC.Collect調用。 我必須時不時地處理長度為500KB(不可避免的大小:-()的字節數組。

  2. 如果發生碎片,如何壓縮內存 - 因為看起來.NET GC並沒有真正有效地做到這一點並導致OOM。

  3. 另外,LOH究竟有85KB的限制? 這是數組整體大小的對象大小嗎? 這對我來說不是很清楚。

  4. 哪些內存計數器可以判斷代碼更改是否實際上減少了OOM的可能性?

提示我已經知道了

  1. 將托管對象設置為null - 將它們標記為垃圾 - 以便垃圾收集器可以收集它們。 這很奇怪 - 在將string []對象設置為null之后, 所有Heaps中#個字節都會出現!

  2. 避免創建> 85KB的對象/數組 - 這不在我的控制范圍內。 所以,可能會有很多LOH。

3。

Memory Leaks Indicators:

# bytes in all Heaps increasing
Gen 2 Heap Size increasing
# GC handles increasing
# of Pinned Objects increasing
# total committed Bytes increasing
# total reserved Bytes increasing
Large Object Heap increasing

我的情況:

  • 我有4 GB,32位機器,上面有Wink 2K3服務器SP2。
  • 我知道應用程序可以使用<= 2 GB的物理RAM
  • 增加虛擬內存(頁面文件)大小在此方案中無效。

作為其OOM問題,我只關注與內存相關的計數器。

請指教! 由於缺乏良好的文檔,我真的需要一些幫助。

您可以嘗試自己匯集和管理大型對象。 例如,如果你經常需要<500k數組並且一次活動的數組很容易被理解,那么你可以避免將它們解除分配 - 這樣如果你一次只需要10個數組,你可能會受到影響固定5mb內存開銷而不是麻煩的長期碎片。

至於你的三個問題:

  1. 是不可能的。 只有垃圾收集器決定何時完成托管對象並釋放內存。 這是使他們成為托管對象的部分原因。

  2. 如果您在不安全的代碼中管理自己的堆並完全繞過大對象堆,則可以執行此操作。 如果你走這條路,你最終會做很多工作並且會帶來很多不便。 我懷疑它對你來說是值得的。

  3. 它是對象的大小,而不是數組中元素的數量。

請記住,碎片僅在釋放對象時發生,而不是在分配對象時發生。 如果碎片確實是你的問題,重復使用大對象將有所幫助。 專注於在應用程序的生命周期中創建更少的垃圾(特別是大型垃圾),而不是直接嘗試處理gc實現的細節。

Nayan,這里是您的問題的答案,以及一些額外的建議。

  1. 你不能釋放它們,你只能讓它們更容易被GC收集。 似乎你已經知道了方法:關鍵是減少對象的引用數量。
  2. 碎片化是你無法控制的另一件事。 但是有幾個因素可以影響這個:
    • LOH外部碎裂比Gen2外部碎裂危險性小,因為LOH沒有壓實。 LOH的空閑插槽可以重復使用。
    • 如果引用的500Kb字節數組用作某些IO緩沖區(例如傳遞給某些基於套接字的API或非托管代碼),則它們很可能會被固定。 固定對象不能由GC壓縮,它們是堆碎片最常見的原因之一。
    • 85K是對象大小的限制。 但請記住,System.Array實例也是一個對象,因此所有500K字節[]都在LOH中。
    • 您帖子中的所有計數器都可以提示內存消耗的變化,但在您的情況下,我會選擇BIAH(所有堆中的字節數)和LOH大小作為主要指標。 BIAH顯示所有管理堆的總大小(Gen1 + Gen2 + LOH,確切地說,沒有Gen0 - 但誰關心Gen0,對吧?:)),LOH是放置所有大字節[]的堆。

建議:

  • 已經提出的建議:預先分配和匯集緩沖區。

  • 如果您可以使用任何集合而不是連續的字節數組(如果在IO中使用緩沖區則不是這種情況),則可以采用不同的方法:實現自定義集合,其內部將由許多較小的數組組成。 這類似於來自C ++ STL庫的std :: deque。 由於每個單獨的陣列將小於85K,因此整個集合將不會進入LOH。 使用此方法可以獲得的優勢如下:僅在完整GC發生時收集LOH。 如果你的應用程序中的byte []不是長壽的,並且(如果它們的尺寸較小)將在收集之前進入Gen0或Gen1,這將使GC的內存管理更容易,因為Gen2集合更重要。

  • 關於測試和監控方法的建議:根據我的經驗,需要對GC行為,內存占用和其他與內存相關的內容進行相當長時間的監控,以獲得一些有效且穩定的數據。 因此,每次更改代碼中的某些內容時,請通過監視內存性能計數器進行足夠長的測試,以查看更改的影響。

  • 我還建議您查看GC計數器中的%Time,因為它可以很好地指示內存管理的有效性。 此值越大,應用程序花在GC例程上的時間就越多,而不是處理來自用戶的請求或執行其他“有用”操作。 我無法就此計數器的絕對值表示問題提出建議,但我可以分享我的經驗供您參考:對於我正在處理的應用程序,我們通常將GC中的%Time時間視為高於20%的問題。

此外,如果您共享應用程序的內存相關性能計數器的某些值將非常有用:進程的專用字節和工作集,BIAH,總提交字節數,LOH大小,Gen0,Gen1,Gen2大小,Gen0的數量, Gen1,Gen2集合,GC中的%時間。 這有助於更好地了解您的問題。

另一個指標是Bytes in all Heaps觀看Private BytesBytes in all Heaps 如果Private Bytes Bytes in all Heaps增長速度快於Bytes in all Heaps ,則會出現非托管內存泄漏。 如果“所有堆中的字節數”增加的速度超過“私有字節數”,那么它就是一個管理泄漏。

要糾正@Alexey Nedilko所說的話:

“LOH外部碎片比Gen2外部碎片更不危險,因為LOH沒有壓實.LOH的空閑插槽可以重復使用。”

是完全錯誤的 Gen2被壓縮,這意味着收集后永遠不會有自由空間。 LOH沒有被壓縮(正如他正確提到的那樣),是的,免費插槽被重復使用。 但是如果可用空間不是連續的以適合所請求的分配,則段大小會增加 - 並且可以繼續增長和增長 因此,你可以最終得到LOH中從未填補的空白。 這是OOM的常見原因,我在很多內存轉儲中看到了這一點。

雖然現在GC API中的方法(從.NET 4.51開始)可以調用以編程方式壓縮LOH,但我強烈建議避免這種情況 - 如果應用程序性能是一個問題。 在運行時執行此操作非常昂貴,並且會顯着損害您的應用程序性能。 GC的默認實現是高效的原因,這就是為什么他們首先省略了這一步驟。 IMO,如果你發現由於LOH碎片你必須調用它,你在你的應用程序中做錯了 - 它可以通過池化技術,拆分數組和其他內存分配技巧來改進。 如果這個應用程序是一個離線應用程序或一些性能不是很大的批處理過程,也許它並不是那么糟糕,但我會充分利用它。

關於如何發生這種情況的一個很好的視覺例子是 - 大型物體堆的危險大型物體堆未被發現 - 由Maoni(CLR的GC團隊負責人)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM