Прежде чем я начну с настоящего вопроса, позвольте мне сказать, что я могу неправильно понять некоторые детали. Если да, пожалуйста, арестуйте меня по этим вопросам, а также вместо того, чтобы отвечать на мой вопрос.
В основном мой вопрос касается библиотек DLL и .NET. У нас есть приложение, которое использует довольно много памяти, и мы пытаемся выяснить, как правильно это измерить, особенно когда проблема в основном возникает на компьютерах клиентов.
Меня поразило то, что у нас есть довольно большие сборки .NET с сгенерированным ORM-кодом.
Если бы я использовал неуправляемую (Win32) DLL с уникальным базовым адресом, несколько одновременных процессов на одном компьютере загружали бы DLL один раз в физическую память и просто отображали ее в виртуальную память для всех приложений. Таким образом, физическая память будет использована для этой DLL один раз.
Вопрос в том, что происходит со сборкой .NET. Эта DLL содержит IL, и хотя эта ее часть может совместно использоваться приложениями, как насчет JITted-кода, который является результатом этого IL? Это поделено? Если нет, как мне измерить, чтобы выяснить, действительно ли это способствует возникновению проблемы или нет? (Да, я знаю, это поможет, но я не собираюсь тратить на это много времени, пока это не станет самой большой проблемой).
Кроме того, я знаю, что мы не изучили базовый адрес для всех сборок .NET в нашем решении, нужно ли сборкам .NET это делать? И если да, то есть ли какие-то рекомендации по определению этих адресов?
Любое понимание этой области было бы очень желанным, даже если окажется, что это не большая проблема, или даже не проблема вообще.
Изменить: только что нашел этот вопрос: Сборки .NET и перебазирование DLL, что частично отвечает на мой вопрос, но я все же хотел бы знать, как JITted-код влияет на все это.
Из этого вопроса и принятого ответа следует, что код JITted помещается в кучу, что означает, что каждый процесс будет загружать общий двоичный образ сборки и создавать частную копию кода JITted внутри своего собственного пространства памяти.
Есть ли у нас способ это измерить? Если окажется, что это приводит к появлению большого количества кода, нам придется больше смотреть на сгенерированный код, чтобы понять, нужно ли нам его корректировать.
Изменить: сюда добавлен более короткий список вопросов:
- Есть ли смысл в том, чтобы убедиться, что базовые адреса сборок .NET уникальны и не перекрываются, чтобы избежать перебазирования dll, которая будет в основном использоваться, чтобы просто получить код IL для JITting?
- Как я могу измерить, сколько памяти используется для JITted-кода, чтобы выяснить, действительно ли это проблема?
Ответ от @Brian Rasmussen здесь указывает, что JITting будет создавать копии JITted-кода для каждого процесса, как я и ожидал, но при перебазировании сборок на самом деле будет эффект в отношении уменьшения использования памяти. Мне придется покопаться в инструментах WinDbg + SoS, о которых он упоминает, что-то, что у меня было в моем списке некоторое время, но теперь я подозреваю, что не могу больше откладывать это :)
Изменить. Я нашел несколько ссылок по этой теме: