4

假设我有两个完全独立的 .NET 应用程序Foo.exeBoo.exe,它们都使用TestLib.dll位于 Foo 和 Boo 的 bin 文件夹中的同一个库(两个副本)。

.NET 会加载这两个 dll,浪费size_of_dll * 2RAM 的大小,还是会检查强大的程序集名称、大小等......并且只加载和加载两个程序集之一?

4

5 回答 5

4

您说得对,DLL 的一个特性是使用该 DLL 的多个进程可以共享某些部分以减少内存使用(这是 Windows 特性,并非特定于 .Net),但是我相当确定为此要使两个进程工作,必须在磁盘上加载相同的物理 DLL,在这种情况下,您描述的场景不会发生这种情况。

如果您改为安装到一个公共位置(例如 GAC),那么 Windows 将能够跨多个进程共享 DLL 的某些部分以节省内存。对于 .net 程序集,您还需要对程序集进行NGen 以利用这一点

请注意,“节省”的内存量并不是 size_of_dll因为该 DLL 映像的某些部分不能共享,即该 DLL 的任何部分都可以修改。这些部分仍然在多个进程中重复,以确保应用程序不会意外修改彼此的数据。

于 2013-05-20T16:23:29.280 回答
2

使用两个 .net 4.0 项目、一个类库和 Process Explorer 对此进行了测试——默认情况下,Visual Studio 会将引用的 dll 复制到项目的bin目录中。

Process Explorer 为引用的 dll 返回两个不同的地址,而为其他特定于 windows 的库返回相同的地址。

结论:是的,对于同一库在不同文件夹中的两个副本,由两个应用程序加载,同一个库可能会被加载两次。

于 2013-05-20T16:34:10.613 回答
2

如果您希望多个进程共享同一个程序集,您有两种选择:

  1. 您可以将程序集放在GACorGlobal Assembly Cache中。您可以使用GacUtil来做到这一点。
  2. 您可以使用配置文件和codeBase元素在一小部分应用程序之间共享私有部署的程序集。
于 2013-05-20T16:08:27.763 回答
2

是的,每个 AppDomain 将加载一次 DLL。但是,您可以跨多个 AppDomain 共享 DLL 以减少内存使用。如本代码项目文章中所述

如果一个程序集被一个进程中的多个域使用,则程序集的代码(但不是它的数据)可以由引用该程序集的所有域共享。这减少了运行时使用的内存量。

于 2013-05-20T15:51:29.727 回答
0

我认为您是在询问程序集的代码是每个进程加载一次还是在本机 dll 等进程之间共享。答案是否定的,主要是因为代码不是原生的,它必须是 JIT。每个进程都会发生 Jitting。Pre-jitted 程序集 (ngen) 能够共享代码。

于 2013-05-20T16:24:53.727 回答