在开始真正的问题之前,我想说的是,我可能会弄错一些细节。如果是这样,请逮捕我,甚至不要回答我的问题。
我的问题基本上是关于 DLL 和 .NET。我们有一个应用程序使用了大量内存,我们正在尝试找出如何正确测量内存的方法,特别是当问题主要发生在客户端计算机上时。
让我印象深刻的一件事是,我们有一些相当大的 .NET 程序集,其中包含生成的 ORM 代码。
如果我使用具有唯一基地址的非托管 (Win32) DLL,则同一台计算机上的多个并发进程会将 DLL 加载到物理内存中一次,然后将其映射到所有应用程序的虚拟内存中。因此,该 DLL 将使用一次物理内存。
问题是 .NET 程序集会发生什么情况。该 DLL 包含 IL,尽管这部分内容可能在应用程序之间共享,但是从该 IL 生成的 JIT 代码又如何呢?是共享的吗?如果不是,我该如何衡量以确定这实际上是否导致了问题? (是的,我知道,它会有所帮助,但我不会花太多时间在这上面,直到它成为最大的问题)。
另外,我知道我们还没有查看解决方案中所有 .NET 程序集的基地址,.NET 程序集是否有必要这样做?如果是这样,是否有一些关于如何确定这些地址的指南?
任何对此领域的见解都将受到欢迎,即使事实证明这不是一个大问题,甚至根本不是一个问题。
Edit: 刚刚发现这个问题:.NET 程序集和 DLL 变基 https://stackoverflow.com/questions/352519/-net-assemblies-and-dll-rebasing这部分回答了我的问题,但我仍然想知道 JITted 代码如何影响所有这些。
从该问题及其接受的答案看来,JITted 代码放置在堆上,这意味着每个进程将加载共享的二进制程序集映像,并在其自己的内存空间内生成代码的私有 JITted 副本。
我们有什么办法可以衡量这个吗?如果这会生成大量代码,我们就必须更多地查看生成的代码以确定是否需要调整它。
Edit:此处添加了较短的问题列表:
- 确保 .NET 程序集的基址是唯一且不重叠的,以避免对主要用于获取 IL 代码进行 JITting 的 dll 进行变基,是否有任何意义?
- 如何测量 JIT 代码使用了多少内存来确定这是否确实是一个问题?
答案由@布莱恩·拉斯穆森 https://stackoverflow.com/users/38206/brian-rasmussen here https://stackoverflow.com/questions/479146/dlls-memory-mapping-base-address-memory-usage-and-net#479209表明 JITting 将生成 JITted 代码的每个进程副本,正如我所预期的那样,但重新设置程序集的基址实际上会对减少内存使用产生影响。我将不得不深入研究他提到的 WinDbg+SoS 工具,这些工具我已经在我的清单上有一段时间了,但现在我怀疑我不能再拖延了:)
Edit:我发现了一些关于该主题的链接:
- 重新设置所有库程序集的基础 http://vanryswyckjan.blogspot.com/2005/11/rebase-all-your-library-assemblies.html
- MSDN:Win32 DLL 变基:整个故事 http://msdn.microsoft.com/en-us/library/ms810432.aspx