2010-07-21 61 views
44

.NET程序首先編譯爲MSIL代碼。執行時,JIT編譯器會將其編譯爲本機機器碼。緩存.NET JIT編譯代碼在哪裏?

我在想:

這些JIT編譯的機器代碼存儲在哪裏?它只存儲在進程的地址空間中嗎?但是由於該程序的第二次啓動比第一次啓動快得多,我認爲即使在執行完成後,這個本地代碼也必須存儲在某個磁盤上。但是哪裏?

回答

69

內存。它可以緩存,這就是ngen.exe的工作。它生成程序集的.n​​i.dll版本,其中包含機器代碼並存儲在GAC中。之後會自動加載,繞過JIT步驟。

但這與你的程序第二次啓動得更快沒有關係。你第一次有所謂的「冷啓動」。這完全由在硬盤驅動器上查找DLL所花費的時間所支配。第二次,你有一個溫暖的開始,這些DLL已經在文件系統緩存中可用。

磁盤緩慢。 SSD是一個明顯的問題。

Fwiw:這不是一個獨立於託管代碼的問題。有大量DLL的大型非託管程序也有它。目前大多數開發機器上的兩個規範示例是Microsoft Office和Acrobat Reader。他們作弊。安裝時,他們在運行註冊表項或啓動文件夾中放置一個「優化器」。所有這些優化器都會加載主程序使用的所有DLL,然後退出。這會啓動文件系統緩存,當用戶隨後使用該程序時,它將快速啓動,因爲其熱啓動很快。

就我個人而言,我覺得這非常煩人。因爲他們真的所做的是減慢我可能要登錄後啓動的任何其他程序。這很少是Office或Acrobat。如果需要刪除這些優化器時,我會重複刪除這些優化器。

您也可以使用這個技巧,但請使用它負責任。

+17

Vista和Windows 7內置了這種DLL緩存技巧,因此您不必再製作「應用程序加速器」。 Superfetch記錄最常用的應用程序,並在啓動後讀取這些文件。它比加速器應用更好,因爲它關注當前的內存使用和實際的應用程序使用情況。 – 2011-01-19 19:07:32

+1

@Hans:您告訴''它生成程序集的.n​​i.dll版本,其中包含機器代碼並存儲在GAC中''。我有一些疑問.. GAC僅用於存儲公共程序集,對嗎?它是否存儲我運行的'exe'的'Native Image'? – Sreekumar 2013-04-03 12:24:56

+0

是的,這就是答案所說的。它是隱藏的,但您可以通過啓動命令提示符來看到它。輸入'dir c:\ windows \ assembly'來列出GAC中的目錄。 – 2013-04-03 12:49:38

2

簡而言之,IL是針對程序的每次調用進行JIT編譯的,並且保存在進程地址空間的代碼頁中。請參閱Richter的第1章以獲得有關.NET執行模型的詳盡介紹。

1

我相信JIT編譯的代碼永遠不會被存儲或換出內存。您在程序集的第二次執行時認識到的性能提升是由於相關程序集已存在於內存或磁盤緩存中。

+0

只有內核驅動程序可以防止代碼被換出。 JIT編譯代碼可以像應用程序內存中的任何其他頁面一樣分頁。 – 2010-07-31 14:38:54

7

JIT編譯的機器代碼被緩存在每個方法的內存中,每次方法首次執行。我認爲它不會被緩存到磁盤。

您可能會發現第二次加載的過程更快,因爲Windows在第一次運行時緩存(在內存中)進程(dll,資源等)使用的文件。在第二次運行中,不需要轉到磁盤,在第一次運行時可能會這樣做。

您可以通過running NGen.exe確認此事實際爲您的體系結構預編譯機器代碼,並比較第一次和第二次運行的性能。我敢打賭,由於操作系統中的緩存,第二次運行仍然會更快。

+0

你知道windows在緩存這些被進程使用的文件(dll,資源等)嗎? – Sreekumar 2013-04-03 12:30:05

+0

@Sreekumar:在RAM中,這幾天和其他操作系統一樣。 – SamB 2015-12-08 05:00:49

11

正如其他人指出的那樣,代碼在每個進程的基礎上進行JIT處理,而不是緩存 - 第二次加載時看到的加速是操作系統磁盤高速緩存(即內存中)的組件。

但是,雖然在框架的桌面\服務器版本中沒有緩存(除了操作系統磁盤緩存),但在另一個版本的框架中緩存了JIT的機器代碼。

感興趣的是.Net Compact Framework(適用於Windows Phone 7的NETCF)。最近的進展看到JIT'd代碼確實被緩存的進程之間共享一些JIT'd框架代碼。這主要是爲了獲得更好的性能(加載時間和內存使用率)在受限設備(如手機)中執行。

因此,在回答這個問題時,CLR的desktop \ server版本中沒有JIT'd代碼的直接框架緩存,但是最新版本的緊湊框架即NETCF。

參考:我們認爲在共享

http://blogs.msdn.com/b/abhinaba/archive/2010/04/28/we-believe-in-sharing.aspx

1

是的,NGEN.EXE會在GAC中放置.NET可執行文件的JIT編譯版本,即使在MSIL版本不存在的情況下也是如此。我已經嘗試過,但無濟於事。 我相信,除非原始MSIL版本也在GAC中,並且從那裏加載 ,否則GAC中的JIT版本將不會被使用。我也相信即時JIT編譯(而不是 NGEN)永遠不會被緩存;它們只佔用進程 的內存。

我相信這從閱讀MS文檔和各種實驗。我歡迎 確認或反駁我的那些「知道」的人的斷言。