Dot-Net

.NET 程序記憶體使用 = 5x CLR 堆記憶體?

  • August 26, 2021

我正在嘗試解決一些記憶體使用問題。總的來說,我的應用程序收集了一些數據值並使用 C1 WPF 圖表和數據網格將它們視覺化,最終將所有內容放入 PDF 報告中。

使用 YourKit 分析我的程序我面臨的情況是,CLR 堆大小約為 120MB(這很好),而程序記憶體大小約為 580MB。這幾乎是我的實際 CLR 堆大小的記憶體消耗的 5 倍。我的 CLR 峰值大小為 220MB,而程序記憶體分配為 710MB。

我很清楚我的對象堆、堆棧等需要一些成本。在 Java JVM 中,我習慣的典型因素約為 1.5 倍。

如何解釋這種過多的記憶體成本?這些程序是否只是分配空閒的備用堆空間?如果是,這是否解釋了 710MB 與 220MB?

這裡有幾個額外的說明。儘管我不確定您所說的“CLR 堆大小”是什麼意思。根據您使用的 .NET 執行時,CLR 使用 8 或 9 個不同的堆 - 因此您在堆大小與 VM 大小中看到的記憶體說明了一些差異:

  1. Loader Heap:包含 CLR 結構和類型系統
  2. 高頻堆:statics, MethodTables, FieldDescs, interface map
  3. 低頻堆:EEClass、ClassLoader 和查找表
  4. 存根堆:用於 CAS、COM 包裝器、P/Invoke 的存根
  5. 大對象堆:需要超過 85k 字節的記憶體分配
  6. GC Heap:使用者分配給應用程序私有的堆記憶體
  7. JIT 程式碼堆:由 mscoreee(執行引擎)和用於託管程式碼的 JIT 編譯器分配的記憶體
  8. 程序/基堆:互操作/非託管分配、本機記憶體等
  9. 在 .NET 5 中添加固定對象堆 (POH)

可能導致過多記憶體使用的另外兩個項目是記憶體碎片(主要發生在 LOH 或大型對象堆上)或大量執行緒。

記憶體碎片的原因有很多,排除這種情況的最佳方法是使用 WinDbg 分析 GC 堆上每個段的段大小。

就大量執行緒而言,您為應用程序使用的每個執行緒分配了 1MB(對於 x86 程序)或 4MB(對於 x64 程序)的堆棧空間。該記憶體被放置在程序/基堆中。因此,如果您有 100 個執行緒,則最多可以額外使用 100MB/400MB 的記憶體。

高溫高壓

引用自:https://stackoverflow.com/questions/10121943