3

在终端服务环境中运行 .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 书籍都掸掉了,但我已经没有办法尝试解决这个问题了;谁会通过帮助消除“我不明白发生了什么”的那种可怕的唠叨感觉来度过我的一天!?!:)

4

1 回答 1

4

I think you are looking directly at module pages. When you JIT code, it won't show up under your DLL - it shows up in memory the runtime allocates. The module pages you are looking at are mostly metadata and IL, which is why they are still sharable.

As an experiment, I wrote a small program that generates 30K static methods and calls them. On my system, the JIT version of this program has 8.2 MB of private comitted memory, while the NGEN version has 3.8.

Even within your module pages, however, NGEN does help with memory use. When the runtime is able to load an NGEN image, it doesn't have to read the metadata of your module in order to JIT the code. The JIT version of my test application is using 2.3MB of working set. The NGEN version is using 32 kilobytes.

NGEN should also help your startup time. Impact to warm startup time can be negligable, but the impact to cold startup time (saving reading all those pages off the disk) can be noticable.

于 2009-04-18T14:46:26.233 回答