在什么情况下.NET进程和AppDomain在内存中共享加载的程序集?

时间:2015-07-08 09:33:46

标签: asp.net .net .net-assembly shared-memory appdomain

我正在寻找有关.NET应用程序何时以及如何共享加载程序集的更多详细信息。我有兴趣在OS进程之间共享,也在同一进程内的AppDomains之间共享。共享程序集通过避免在内存中拥有相同程序集的多个副本来减少系统内存使用量,我认为这是主要的好处,但有兴趣知道是否还有其他好处和/或影响。

到目前为止我学到的内容摘要......

  1. Sysinternals process explorer可用于列出.NET进程的AppDomain以及加载到每个AppDomain中的程序集。

  2. .NET进程似乎始终将“核心”程序集加载到名为“SharedDomain”的AppDomain中(假设这是在当前进程中的AppDomain之间共享,这是合理的。)

  3. 任务管理器和Process Explorer报告“工作集共享”和“工作集可共享”的内存使用数量并不是无关紧要,但目前尚不清楚共享内容。 (它是共享AppDomain中的'核心'程序集吗?其他[非核心]程序集也是共享的吗?

  4. 在一个简单的测试中,我推出了两个独立的.NET应用程序副本,并为每个应用程序附加了一个Visual Studio调试器。 “模块”视图显示已加载的程序集及其在内存中的地址。在我的测试用例中,每个加载的模块都位于两个进程中的相同地址。 (这是否表示共享,或者这个虚拟地址空间是否必须共享?)

  5. ASP.NET 4.5支持通过称为程序集实习的机制共享程序集(请参阅Look at Sharing Common Assemblies in ASP.NET 4.5Sharing Common AssembliesSharing common assemblies with aspnet_intern.exe)。它似乎通过设置文件系统符号链接(符号链接)来工作,以便不同的Web应用程序指向共享bin文件夹,因此这引发了一个问题,即ASP.NET是否只是使用符号链接来触发.NET中的标准程序集共享行为,或者是否有更具体的ASP.NET和IIS AppPools。

  6. 请注意。在安装了Visual Studio 2013的计算机上,可以在以下位置找到aspnet_intern.exe:

      

    C:\ Program Files(x86)\ Microsoft SDKs \ Windows \ v8.1A \ bin \ NETFX 4.5.1   工具\

    在.NET和Windows Server的更高版本中,ASP.NET启动时间和内存使用情况有了进一步的改进;请参阅ASP.NET App Suspend – responsive shared .NET web hostingPerformance Improvements for ASP.NET Shared Hosting Scenarios in .Net 4.5,但我不确定这些更改与此问题的相关性。

    ASP.NET程序集共享也包含在Introducing .NET 4.5一书中。

    还想知道是否共享JITted代码,因为加载的程序集由MSIL,资源,元数据等组成,并且当代码被JIT时必须分配更多的内存。

    在紧凑框架(We Believe in Sharing,MSDN博客,Abhinaba Basu)中也有关于程序集共享的讨论

    --- --- UPDATE

    我使用sysinternals VMMap tool来检查两个AppPools,一个用asp.net程序集internign设置,另一个没有。我还“触摸”了一个测试aspx页面,导致ASP.NET加载所有程序集(并且global.asax运行少量代码,因此导致一些JITting)。

    报告的两个AppPools的内存使用数据非常相似,工作集,WS Private和WS Shareable基本相同。但是,在“实习”AppPool中,WS Shared要大得多。这是意外的(对我来说),因为没有其他进程可以与之共享,但VMMap显示的是内存块(标记为'.text'并具有执行/读保护),这些内存块在实习AppPool中显示为共享内存,而另一个AppPool中的相同程序集不共享。我对此的解释是,进程中的虚拟内存块被映射到同一个物理内存,然后报告为“WS Shared”。

    ASLR

    关于装配空间布局随机化。 VMMap工具显示许多类型为“Image(ASLR)”的内存块。 ASLR随机化了内存中程序集的位置以阻止恶意软件,我想知道这是否会阻止程序集实习工作正常。使用EMET tool禁用机器的ASLR会导致程序集地址更加规则,但不会更改报告的内存数,因此它似乎不会影响程序集实习。值得注意的是VMMap仍然显示带有'ASLR'的图像,我怀疑这只是意味着装配/图像被标记为支持/允许ASLR,而不是ASLR生效。

1 个答案:

答案 0 :(得分:1)

发生程序集共享的一种情况是使用ngen.exe编译为本机代码的程序集。让我引用" CLR来自C#" (第1章)

  

NGen.exe工具在两种情况下很有趣:

     

...

     

减少应用程序的工作集 - 如果您认为程序集将同时加载到多个进程中,则在该程序集上运行NGen.exe可以减少应用程序的工作集。原因是因为NGen.exe工具将IL编译为本机代码并将输出保存在   单独的文件。此文件可以内存映射到多进程   同时寻址空间,允许共享代码;不   每个进程都需要自己的代码副本。