.NET程序集的内存使用情况

4
假设我有两个完全独立的.NET应用程序,Foo.exeBoo.exe,这两个应用都使用位于Foo和Boo(两个副本)的bin文件夹中的相同库TestLib.dll
.NET会加载这两个dll吗?是否会浪费size_of_dll * 2大小的RAM,或者它会检查强名称、大小等,并且只加载其中一个程序集呢?

简而言之 - 是的。请查看此链接http://msdn.microsoft.com/en-us/library/windows/desktop/aa374224(v=vs.85).aspx - Uzzy
我不知道Windows是否会这样做(例如对于自己签名的程序集),但这样做是疯狂的。即使您拥有相同的名称、版本和大小,从不同来源、提供者或地区(或已打补丁的程序集)获取的两个程序集之间仍然可能存在位差异。 - mrówa
汇编代码的大小与程序在运行时可以分配的内存数量(高达8TB)相比微不足道。 - OpenMinded
不行,我们的程序有超过400MB的程序集,现在大部分都被用于不同的应用程序中,所以用户会浪费很多内存!4个应用程序 * 300MB。 - Brans Ds
只是举个例子,我们如何浪费RAM。 - Brans Ds
@BransDs,我实现了你刚刚删除的解决方案,但它按预期工作。它没有进入if条件。那是什么? - Freelancer
5个回答

4
您是正确的,DLL的一个特性是多个使用该DLL的进程可以共享某些部分以减少内存使用(这是Windows的一个特性,不特定于.Net),但我相当确定,为了使此功能正常工作,两个进程必须加载同一物理磁盘上的DLL,而在您描述的情况下,这种情况不会发生。
如果您将其安装到公共位置(例如GAC),则Windows将能够跨多个进程共享DLL的某些部分以节省内存。对于.net程序集,在利用此功能之前,您还需要NGen程序集
请注意,“保存”的内存量不是 size_of_dll,因为该DLL映像的某些部分无法共享,即任何可能被修改的DLL部分。这些部分仍然在多个进程之间重复,以确保应用程序不会意外修改彼此的数据。

如果您将其安装到公共位置(例如GAC),那么Windows将能够在多个进程之间共享DLL的某些部分以节省内存。真的吗?此外,我认为它们可能还需要预先JIT(ngen)? - YK1
@YK1 是的,看起来是这样的情况。 - Justin
1
我认为只使用Ngen就足够了 - 但如果程序集在GAC中,则其性能更佳。GAC不是必需的。无论如何,我会点赞你的答案,因为它比我的更完整。干杯! - YK1

2
是的,DLL将会在每个AppDomain中加载一次。但是,您可以跨多个AppDomain共享DLL以减少内存使用量。如此代码项目文章所述。
如果一个程序集被进程中的多个域使用,则程序集的代码(但不包括其数据)可以由引用该程序集的所有域共享。这样可以减少运行时使用的内存量。

我认为AppDomains不能被共享。你可以在AppDomain边界上调用变量,但我还没有找到一种在进程之间“共享”AppDomains的方法。 - Tejas Sharma
不行,但是你可以在多个应用程序域之间共享DLL。 - PHP Rocks
1
不确定您所说的“共享DLL”是什么意思。无论如何,问题是关于两个独立进程是否会使用相同的程序集,而不是关于AppDomains - Tejas Sharma

2
如果您希望多个进程共享同一个程序集,您有两个选择:
  1. 您可以将程序集放置在GAC全局程序集缓存中。您可以使用GacUtil来完成这一操作。
  2. 您可以使用配置文件和codeBase元素将私有部署的程序集在一小组应用程序之间共享。

谢谢。我知道...不仅可以放在GAC中,还可以使用AssemblyResolve事件在不同的进程中使用相同的程序集...但我开始怀疑了。也许.NET会检查所有程序集,并通过共享来自GAC之外不同位置的相同程序集来减少内存使用和加载时间.. - Brans Ds
看看我的最新编辑,你甚至可以分享私有部署的程序集! - Tejas Sharma

2

我已经测试了两个 .net 4.0 项目,一个是类库,另一个是进程资源管理器(Process Explorer)——默认情况下,Visual Studio会将引用的dll文件复制到项目的bin目录中。

进程资源管理器返回了两个不同的地址,而其他Windows特定的库则返回相同的地址。

结论:对于在不同文件夹中加载的两个应用程序所使用的同一库,该库可能被加载两次。


0

我认为你在问汇编代码是否每个进程加载一次,还是像本机dll一样在进程之间共享。答案是否定的,主要是因为代码不是本地代码,必须进行JIT编译。JIT编译发生在每个进程中。预编译的程序集(ngen)可以共享代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接