Где хранится JNET-скомпилированный код .NET? - PullRequest
46 голосов
/ 21 июля 2010

.NET-программа сначала компилируется в код MSIL. Когда он выполняется, JIT-компилятор скомпилирует его в машинный код.

Мне интересно:

Где хранится этот JIT-скомпилированный машинный код? Хранится ли он только в адресном пространстве процесса? Но поскольку второй запуск программы происходит намного быстрее, чем в первый раз, я думаю, что этот собственный код должен быть сохранен где-то на диске даже после завершения выполнения. Но где?

Ответы [ 6 ]

73 голосов
/ 21 июля 2010

Память. можно кэшировать, это работа ngen.exe.Он генерирует версию сборки .ni.dll, которая содержит машинный код и хранится в GAC.Который автоматически загружается позже, минуя шаг JIT.

Но это не имеет отношения к тому, почему ваша программа запускается быстрее во второй раз.В первый раз у вас так называемый «холодный старт».Который полностью доминирует время, потраченное на поиск DLL на жестком диске.Во второй раз, когда у вас горячий старт, библиотеки DLL уже доступны в кеше файловой системы.

Диски работают медленно.SSD - очевидное исправление.

Замечание: это не проблема, которая является исключительной для управляемого кода.У больших неуправляемых программ с большим количеством DLL тоже есть.Два канонических примера, представленные на большинстве машин разработчика, - это Microsoft Office и Acrobat Reader.Они обманывают.После установки они помещают «оптимизатор» в раздел реестра «Выполнить» или в папку «Автозагрузка».Все, что делают эти оптимизаторы - это загружают все библиотеки DLL, которые использует основная программа, и завершают работу.Это заполняет кэш файловой системы, когда пользователь впоследствии использует программу, она запускается быстро, так как ее горячий запуск быстрый.

Лично я считаю это чрезвычайно раздражающим.Потому что то, что они действительно делают, - это замедляет работу любой другой программы, которую я могу захотеть запустить после входа в систему. Это редко бывает Office или Acrobat.Я хочу удалить эти оптимизаторы несколько раз, если это необходимо, когда обновленное обновление возвращает их обратно.

Вы также можете использовать этот прием, но ответственно, пожалуйста.

11 голосов
/ 21 июля 2010

Как уже отмечали другие, в вашем случае код является JIT для каждого процесса и не кэшируется - ускорение, которое вы наблюдаете при второй загрузке, - это кэширование диска ОС (т. Е. В памяти) сборки.

Однако, хотя кэширование (кроме кэширования диска ОС) в версии платформы для настольных компьютеров и серверов отсутствует, в другой версии платформы кэшируется машинный код JIT.

Интерес представляет то, что происходит в .Net Compact Framework (версия NETCF для Windows Phone 7). Последние достижения показывают совместное использование некоторого кода JIT-структуры между процессами, где JIT-код действительно кэшируется. Это было сделано в первую очередь для повышения производительности (время загрузки и использование памяти) в ограниченных устройствах, таких как мобильные телефоны.

Таким образом, в ответ на этот вопрос нет прямого кэширования каркаса JIT-кода в версии CLR для настольных компьютеров и серверов, но будет в последней версии компактной платформы, т.е. NETCF.

Ссылка: Мы верим в обмен

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

7 голосов
/ 21 июля 2010

JIT-скомпилированный машинный код кэшируется в памяти для каждого метода каждый раз, когда метод выполняется в первый раз.Я не думаю, что он когда-либо кэшируется на диск.

Вы можете обнаружить, что процесс загружается быстрее во второй раз, потому что Windows кэшировала (в памяти) файлы, используемые вашим процессом (библиотеки, ресурсы и т. Д.) на первом запуске.При втором запуске нет необходимости переходить на диск, где это могло быть сделано при первом запуске.

Вы можете подтвердить это, запустив NGen.exe для фактической предварительной компиляциимашинный код для вашей архитектуры, и сравните производительность первого и второго прогонов.Держу пари, что второй прогон все равно будет быстрее из-за кеширования в ОС.

2 голосов
/ 21 июля 2010

Короче говоря, IL-файл JIT-компилируется для каждого вызова программы и поддерживается в кодовых страницах адресного пространства процесса.См. Главу 1 Рихтера , где подробно рассматривается модель исполнения .NET.

1 голос
/ 12 сентября 2013

Да, NGEN.EXE поместит скомпилированную JIT-версию исполняемого файла .NET в GAC, даже если версии MSIL там нет. Я пробовал это, но безрезультатно. Я полагаю, если оригинальная версия MSIL также не находится в GAC и не будет загружена оттуда версия JIT в GAC не будет использоваться. Я также считаю, что JIT-компиляции на лету (, а не NGEN) никогда не кэшируются; они занимают процесс только память.

Я верю в это из чтения документа MS и из различных экспериментов. Я бы приветствовал либо подтверждение или опровержение моих утверждений от тех, "кто знает".

1 голос
/ 21 июля 2010

Я считаю, что JIT-скомпилированный код никогда не сохраняется и не выгружается из памяти. Повышение производительности, которое вы ощущаете при втором выполнении сборки, происходит из-за того, что зависимые сборки уже находятся в памяти или дисковом кеше.

...