Dot-Net

DLL、記憶體映射、基地址、記憶體使用和 .NET?

  • January 26, 2009

在我開始真正的問題之前,讓我先說一下我可能會在這裡弄錯一些細節。如果是這樣,請在這些問題上逮捕我,甚至不要回答我的問題。

我的問題基本上是關於 DLL 和 .NET。我們有一個使用大量記憶體的應用程序,我們正試圖弄清楚如何正確測量這一點,尤其是當問題主要發生在客戶的電腦上時。

讓我印象深刻的一件事是,我們有一些相當大的 .NET 程序集,其中包含生成的 ORM 程式碼。

如果我使用具有唯一基地址的非託管 (Win32) DLL,同一台機器上的多個同時程序會將 DLL 載入到物理記憶體中,然後將其映射到所有應用程序的虛擬記憶體中。因此,該 DLL 將使用一次物理記憶體。

問題是 .NET 程序集會發生什麼。這個 DLL 包含 IL,雖然它的這一部分可能在應用程序之間共享,但是由這個 IL 產生的 JITted 程式碼呢?是共享的嗎?如果不是,我如何衡量以找出這實際上是否導致了問題?(是的,我知道,它會有所貢獻,但在它成為最大的問題之前,我不會花太多時間在這上面)。

另外,我知道我們沒有查看解決方案中所有 .NET 程序集的基地址,.NET 程序集是否有必要這樣做?如果是這樣,是否有一些關於如何確定這些地址的指南?

對此領域的任何見解都將受到歡迎,即使事實證明這不是一個大問題,甚至根本不是問題。


編輯:剛剛發現這個問題:.NET 程序集和 DLL rebase部分回答了我的問題,但我仍然想知道 JITted 程式碼是如何影響所有這些的。

從該問題及其接受的答案看來,JITted 程式碼放置在堆上,這意味著每個程序將載入共享的二進製程序集映像,並在其自己的記憶體空間內生成程式碼的私有 JITted 副本。

我們有什麼方法可以衡量這個嗎?如果這會產生大量程式碼,我們將不得不更多地查看生成的程式碼以確定是否需要對其進行調整。


編輯:在這裡添加了一個較短的問題列表:

  1. 確保 .NET 程序集的基地址是唯一的且不重疊以避免重新設置主要用於將 IL 程式碼從 JITting 中提取出來的 dll 是否有任何意義?
  2. 如何測量 JITted 程式碼使用了多少記憶體來確定這是否真的是一個問題?

@Brian Rasmussen 在此處的回答表明,正如我所料,JITting 將生成 JITted 程式碼的每個程序的副本,但是重新設置程序集實際上會對減少記憶體使用產生影響。我將不得不深入研究他提到的 WinDbg+SoS 工具,我已經在我的列表中列出了一段時間,但現在我懷疑我不能再推遲了 :)


編輯:我在這個主題上找到了一些連結:

這是針對問題 1)

jit 程式碼被放置在一個特殊的堆上。!eeheap您可以使用WinDbg + SoS 中的命令檢查此堆。因此,每個程序都將擁有自己的 jitted 程式碼副本。該命令還將顯示程式碼堆的總大小。

如果您想了解有關從 WinDbg 獲取此資訊的更多詳細資訊,請告訴我。

這是問題2)

根據Expert .NET 2.0 IL Assembly一書,純 IL PE 文件的.reloc一部分僅包含一個用於 CLR 啟動存根的修復條目。因此,在變基期間託管 DLL 所需的修復量是相當有限的。

但是,如果您列出任何給定的託管程序,您會注意到 Microsoft 已重新設置其託管 DLL 的大部分(或全部)基礎。是否應將其視為變基的原因取決於您。

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