在我开始真正的问题之前,让我先说一下,我可能会弄错这里的一些细节。如果是这样的话,也请逮捕我,甚至不要回答我的问题。
我的问题基本上是关于DLL和.NET的。我们有一个应用程序使用了相当多的内存,我们正在努力找出如何正确地测量这个值,特别是当问题主要发生在客户机上时。
有一件事让我感到震惊,那就是我们有一些相当大的带有生成的ORM代码的.NET程序集。
如果我使用的是具有唯一基址的非托管(win32)dll,同一台计算机上的多个同时进程会将该dll一次加载到物理内存中,并将其映射到所有应用程序的虚拟内存中。因此,物理内存将用于此DLL一次。
问题是.NET程序集会发生什么。这个DLL包含IL,虽然它的这一部分可能在应用程序之间共享,但是这个IL产生的抖动代码呢?它是共享的吗?如果不是,我该如何判断这实际上是否是导致问题的原因?(是的,我知道,这是有贡献的,但在这是最大的问题之前,我不会在这方面花太多时间)。
另外,我知道我们还没有查看解决方案中所有.NET程序集的基地址,是否需要.NET程序集执行此操作?如果有的话,有没有一些关于如何确定这些地址的指导方针?
对这一领域的任何洞察都是最受欢迎的,即使这不是一个大问题,甚至根本不是一个问题。
编辑:刚刚发现这个问题:.NET assemblies and DLL rebasing部分回答了我的问题,但我仍然想知道代码因素在所有这些问题中的抖动程度。
从这个问题及其公认的答案来看,抖动的代码被放在一个堆上,这意味着每个进程将加载共享的二进制程序集映像,并在自己的内存空间内生成代码的私有抖动副本。
我们有办法测量这个吗?如果这会产生大量的代码,我们将不得不更多地查看生成的代码,以确定是否需要调整它。
编辑:在此处添加了较短的问题列表:
是否有必要确保.NET程序集的基地址是唯一的且不重叠的,以避免重新调整dll的基地址,该dll主要用于将IL代码从中删除以进行抖动?
我如何测量抖动代码使用了多少内存来判断这是否真的是一个问题?
由@Brian Rasmussenhere得出的答案表明,如我预期的那样,Jitting将生成Jitted代码的每个进程副本,但重新调整程序集的大小实际上会降低内存使用率。我将不得不深入研究他提到的windbg+sos工具,我在清单上已经有一段时间了,但现在我怀疑我不能再推迟了:)
编辑:我在主题上找到的一些链接:
Rebase all your library assemblies
MSDN: Rebasing Win32 DLLs: The Whole Story
最佳答案
这是问题1)
jitted代码被放在一个特殊的堆上。可以使用windbg+sos中的!eeheap
命令检查此堆。因此,每个进程都有自己的JITTED代码副本。该命令还将显示代码堆的总大小。
如果您想了解更多有关从windbg获取此信息的详细信息,请通知我。
这是问题2)
根据书expert.net 2.0 il assembly,纯IL PE文件的.reloc
部分仅包含一个用于clr启动存根的修正项。因此,重新定位期间托管DLL所需的修复量相当有限。
但是,如果您列出任何给定的托管进程,您会注意到Microsoft已经重新调整了它们的大部分(或可能全部)托管DLL。这是否应该被视为重新平衡的原因取决于你自己。