簡體   English   中英

如何防止對象被提升為 gen2

[英]How to prevent object's being promoted to gen2

運行時標記 gen2 memory 區域(又名卡表)通過寫屏障來檢測是否年輕一代 object 引用被寫入 gen2 object。如果之后檢查 gen.0 或 1 集合。 雖然標記部分會影響分配性能,但顯然 GC 會花費更多時間來收集 Gen0 或 1。

我有池對象,這些對象非常頻繁地是短期對象的書面引用。

我想要實現的是讓那些池化對象始終留在 gen0 中,但我想不出任何技術。 我也想討論它是否有益。 也許 GC 團隊應該將其作為一項功能包含在內?

簡而言之,我有長壽的對象。 他們持有對持久性和易失性對象的引用... volitile object 引用非常頻繁地寫入它,這使得它們掃描每個 gen0 + 寫屏障 - 卡表管理開銷。 您認為擠壓最佳性能的最佳方法是什么?

編輯:這是關於零分配 asnctaskmethodbuilder。 將工作樣本上傳到 github: https://github.com/crowo/LightTask/tree/master/LightTask

你描述的問題確實存在。 卡片表掃描和由此產生的促銷確實可能會增加一些開銷。 我已經在我的視頻中解釋了這種機制。 不幸的是,這只是大多數世代 GC 的一個特性和/或警告。 而且,它可能導致裙帶關系

但是,主要問題是這是否是一個真正的問題,或者您只是對發生這種開銷的知識感到不舒服? 換句話說,您應該遵循“先測量”的方法。

不幸的是,沒有超級簡單的指標來衡量這個特定問題的開銷。 但通常我們正在做以下事情:

  • 自 .NET 5 以來,我們在運行時本身中提供了“世代感知分析” ,我們可以在 PerfView 的世代感知視圖中看到。 它將允許您查看哪些 gen1/gen2 對象持有對年輕代的引用。 這在您的情況下可能不是很有用,因為聽起來您已經知道它發生在哪里
  • 記錄 .NET 跟蹤並查找MarkWithType事件。 如果有很多Type="3"事件(它們代表GC_ROOT_OLDER的原因)具有大量Promoted字節,則可能表明您確實可能有問題:
     Event Name Time MSec Process Name Rest MarkWithType 186.370 Process(28820) HeapNum="5" Type="3" Promoted="62,104,694" MarkWithType 186.421 Process(28820) HeapNum="0" Type="3" Promoted="52,687,589" MarkWithType 186.633 Process(28820) HeapNum="3" Type="3" Promoted="49,932,696"
    前提是您還將此類 GC 與較長的暫停時間或GC 中的 % TIme相關聯。

所以,只有當你以某種方式測量它是一個問題,這通常是在有幾十 GB 的容量時,嘗試解決它。 由於這是 .NET GC 構建方式的固有結果,因此沒有簡單的解決方法。 以下是一些典型的想法:

  • 嘗試按照@david-l 的建議拆分 object 結構。 也許舊對象可能僅通過某個索引而不是引用來引用那些年輕的臨時對象
  • 或者只是嘗試按照@holger 的建議重新設計它,以完全避免這些引用
  • 或者使年輕的臨時對象也使用ObjectPool進行池化,以便它們最終都生活在 gen2 中
  • 或者可能是那些在長壽命池對象中內聯的臨時對象結構

暫無
暫無

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

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