共享dll';进程之间的s-虚拟内存不存在;似乎没有什么好处

本文关键字:不存在 什么 dll 进程 之间 共享 虚拟内存 | 更新日期: 2023-09-27 18:00:32

我的意图是在我的应用程序之间共享dll,例如,如果我有两个加载20MB dll的应用程序,而不是一个进程使用200MB内存,另一个进程也使用200MB,那么其中一个进程将从共享中受益,并且只使用180MB内存。我的问题在于记忆的定义,请继续阅读。

我创建了2.net c#应用程序,这些应用程序引用并运行位于GAC中的大型dll(20MB)frm代码。具有NET内存探查器我可以看到,第二个进程使用的实际物理内存确实明显低于第一个进程启动的物理内存(尽管它们完全相同),并且dll位于第一个进程的共享内存下。然而,当用perfmon检查内存计数器时,我发现两个应用程序的虚拟内存的增加(与dll的大小相关)与单独运行每个应用程序时增加的大小相同。

这就引出了一个问题:如果只有物理内存从中受益,但从应用程序的角度来看,虚拟内存才是最重要的,那么共享(内存经济)dll有什么意义呢。

编辑:感谢您的回答。基于这些答案,我想强调的是,我理解在内存中共享dll以保存物理ram的好处。我应该问的更确切的问题是:.net中应用程序之间共享dll的方式对应用程序(而不是系统)有好处吗?我之所以这么问,是因为我确实关心我的应用程序正在使用的虚拟内存量(总计)。

共享dll';进程之间的s-虚拟内存不存在;似乎没有什么好处

RAM很重要。虚拟内存不需要任何成本,它是虚拟的。多个进程共享同一RAM是一件大事。任何Windows进程都依赖kernel32.dll。但RAM中只有一个代码副本。

利用托管程序中共享代码的进程需要运行ngen.exe,以便它们都能获得完全相同的机器代码。如果代码是及时编译的,则不能共享任何内容。

如果只有物理内存从中受益,但从应用程序的角度来看,虚拟内存才是最重要的,那么共享(内存经济)dll有什么意义呢。

我不知道你是怎么得出这个结论的。系统具有有限的物理内存,而不是虚拟内存,因此从长远来看,节省物理内存是最重要的。

您似乎没有正确考虑这一点。应用程序的进程空间就是它的虚拟内存。为了使代码能够运行,必须将其映射到应用程序进程空间中。否则,它将如何执行它实际上看不到的代码?

物理内存是共享的,但CPU必须能够看到虚拟内存才能执行它

这样想吧。假设你和你的邻居共用一个游泳池。出于所有意图和目的,你们每个人都认为游泳池包含在你们的财产中。只有一个物理池存在,但你们每个人都将其视为"虚拟内存"的一部分。

@duskwuff-系统的虚拟内存数量也有限,尽管理论上限制很大(但实际上受到页面文件大小的限制)。除此之外,前面的回答在一定程度上是正确的。

在Windows中,DLL的映像中内置了一个"首选加载地址"。如果这与同一进程中任何其他DLL的加载地址冲突,则加载程序必须"重新设置"DLL的基础,这基本上意味着要遍历并修复DLL中的绝对引用。在这一点上,加载的内容不再与来自磁盘的内容相同,(至关重要的)也不再与加载到任何其他进程地址空间的内容相同——这意味着它不能在进程之间共享。

此外,由于它与磁盘上的不同,如果需要将其交换出去,则需要将其写入页面文件(不存在于物理内存中的虚拟内存位存储在页面文件中)。

因此,尽管我不认为这是您在perfmon中看到的问题的原因,但在构建DLL时值得记住。如果DLL在加载时被重新基于,您将在VS控制台中看到调试输出。

您可以在构建时设置首选加载地址,也可以使用名为rebase post-build的SDK工具。因此,如果您正在构建多个DLL,请确保它们的首选加载地址不会冲突。即使你只构建了一个DLL,你也应该检查它是否与你的应用程序所依赖的任何其他DLL冲突。

我的理解是,通过GAC共享是为了节省硬盘空间,而不是内存空间。正如ghimireniraj所说,每个从GAC调用DLL的应用程序都会获得自己的DLL内存副本。