.NET JIT在可共享页面中的程序集

时间:2009-04-05 20:07:34

标签: .net memory windows-server-2008 jit ngen

在终端服务环境中运行.NET 2.0 WinForms应用程序时,我看到一些我无法解释的意外结果。我读过的所有内容都表明JIT组装(即不使用NGen创建本机图像)会导致所有代码空间都存储在私有页面中,从而增加了工作集大小/内存压力。但是,实际结果(使用Process Explorer,VMMap和WinDbg进行验证)表明,即使是JIT的程序集也确实被放置在可共享的页面中(并且在应用程序的多个实例运行时确实正在共享,即使在单独的TS下也是如此节/使用者)。

任何人都可以解释为什么会这样吗?这是在W2K8服务器环境中运行的,因此ASLR解释了为什么缺少每个程序集和特定基础地址的特定基地址。由此产生的变基不会导致问题。但是,似乎这些不是本机PE映像的事实应该导致这些程序集的代码存储在私有页面中。

当我们开始调查使用NGen来降低内存压力时发现了这一点,但实际上发现它增加了工作集大小 - 因为JIT的组件已经被共享。

我发现的最新参考文献在这里,这与我们的实际发现有所不同:

http://blogs.msdn.com/morgan/archive/2009/03/07/developing-net-applications-for-deployment-on-terminal-services-or-citrix.aspx

编辑:我应该补充一点,自从首次发布问题以来,Windows Server 2003测试框上的更多实验也显示JIT的程序集在进程之间可以共享。我仍然难以理解为什么我能找到的所有建议都表明NGen是必需的,但所有现实世界的证据都与此相矛盾。我真的希望这里的专家可以解释一下。

谢谢!

编辑:我已经删除了所有的.NET / CLR书籍,并且对搜索查询的想法不足以尝试解决这个问题。谁将通过帮助消除“我不明白发生了什么”这种可怕的唠叨感来结束我的一天!?! :)

1 个答案:

答案 0 :(得分:4)

我认为您正在直接查看模块页面。当您使用JIT代码时,它不会显示在您的DLL下 - 它会显示在运行时分配的内存中。您正在查看的模块页面主要是元数据和IL,这就是它们仍然可共享的原因。

作为一个实验,我写了一个小程序,它生成30K静态方法并调用它们。在我的系统上,这个程序的JIT版本有8.2 MB的私有内存,而NGEN版本有3.8。

然而,即使在您的模块页面中,NGEN确实帮助使用内存。当运行时能够加载NGEN映像时,它不必读取模块的元数据以便JIT代码。我的测试应用程序的JIT版本使用2.3MB的工作集。 NGEN版本使用32千字节。

NGEN也应该帮助你的创业时间。对热启动时间的影响可以忽略不计,但是对冷启动时间的影响(保存从磁盘读取所有这些页面)可能是显而易见的。