假设我有两个完全独立的 .NET 应用程序Foo.exe
和Boo.exe
,它们都使用TestLib.dll
位于 Foo 和 Boo 的 bin 文件夹中的同一个库(两个副本)。
.NET 会加载这两个 dll,浪费size_of_dll * 2
RAM 的大小,还是会检查强大的程序集名称、大小等......并且只加载和加载两个程序集之一?
假设我有两个完全独立的 .NET 应用程序Foo.exe
和Boo.exe
,它们都使用TestLib.dll
位于 Foo 和 Boo 的 bin 文件夹中的同一个库(两个副本)。
.NET 会加载这两个 dll,浪费size_of_dll * 2
RAM 的大小,还是会检查强大的程序集名称、大小等......并且只加载和加载两个程序集之一?
您说得对,DLL 的一个特性是使用该 DLL 的多个进程可以共享某些部分以减少内存使用(这是 Windows 特性,并非特定于 .Net),但是我相当确定为此要使两个进程工作,必须在磁盘上加载相同的物理 DLL,在这种情况下,您描述的场景不会发生这种情况。
如果您改为安装到一个公共位置(例如 GAC),那么 Windows 将能够跨多个进程共享 DLL 的某些部分以节省内存。对于 .net 程序集,您还需要对程序集进行NGen 以利用这一点
请注意,“节省”的内存量并不是 size_of_dll
因为该 DLL 映像的某些部分不能共享,即该 DLL 的任何部分都可以修改。这些部分仍然在多个进程中重复,以确保应用程序不会意外修改彼此的数据。
使用两个 .net 4.0 项目、一个类库和 Process Explorer 对此进行了测试——默认情况下,Visual Studio 会将引用的 dll 复制到项目的bin
目录中。
Process Explorer 为引用的 dll 返回两个不同的地址,而为其他特定于 windows 的库返回相同的地址。
结论:是的,对于同一库在不同文件夹中的两个副本,由两个应用程序加载,同一个库可能会被加载两次。
是的,每个 AppDomain 将加载一次 DLL。但是,您可以跨多个 AppDomain 共享 DLL 以减少内存使用。如本代码项目文章中所述。
如果一个程序集被一个进程中的多个域使用,则程序集的代码(但不是它的数据)可以由引用该程序集的所有域共享。这减少了运行时使用的内存量。
我认为您是在询问程序集的代码是每个进程加载一次还是在本机 dll 等进程之间共享。答案是否定的,主要是因为代码不是原生的,它必须是 JIT。每个进程都会发生 Jitting。Pre-jitted 程序集 (ngen) 能够共享代码。