EXE 或 DLL 何时重用“物理”内存?

EXE 或 DLL 何时重用“物理”内存?

多年来,我的应用程序从几 MB 增长到 50 多 MB。为了简化部署,我始终坚持使用单个 EXE 文件,而不是使用较小的 EXE 和大量 DLL(另请参阅我在 StackOverflow 上的问题:https://stackoverflow.com/questions/2881296/one-big-executable-or-many-small-dlls)。

但是,现在有些客户抱怨每个新版本对内存的要求都更高。改用 DLL 可能会解决其中一些问题,因为我认为 Windows 只会在内存中加载一次 DLL(因此,如果有 50 个进程都使用同一个 DLL,则 DLL 只会在物理内存中占用一次空间)。

另一方面,如果我有 50 个进程都使用同一个 EXE 文件,我希望 Windows 也会为多个进程共享此 EXE 文件。但我的印象是 Windows 不会这样做(并且只对 DLL 文件这样做)。这个观察是正确的吗?

如果多个进程使用 DLL,Windows 是否真的会在内存中加载一次?

如果多个进程使用 EXE 文件,Windows 是否也会在内存中加载一次?还是不会?

答案1

首先请注意,DLL 方法和静态构造是进程堆栈占用空间的一部分,因此它们的内存不是动态分配的,所以用额外的 dll 分解不会减少您的实际 RAM 需求。

可以使用以下方法测量进程内存:私人字节(进程的全部内存占用,减去任何共享对象;可能无法反映物理内存的使用情况)工作集字节数(当前正在使用的物理内存,加上共享对象)和工作集私有(使用全部物理内存,没有任何共享对象)。所有这些都可以在 Sysinternal 的 ProcessExplorer 中监控。WS Private 可能是监控程序在主机上施加了多少负载的最佳指标。

答案2

DLL 和 EXE 代码是绝对共享的 - 无论有多少个进程正在使用 EXE 或 DLL,RAM 中都只有一个代码副本。(并且,并非所有代码都必须位于 RAM 中 - 只有最近引用的代码才位于 RAM 中。)

DLL 和 EXE 是映射文件的示例。映射文件确实对进程的总虚拟地址空间有贡献。它们不会对“专用字节”或“已提交”内存(相同的东西,但不同的实用程序使用不同的术语)有贡献。

流程不会,本身,有堆栈。线程有堆栈。(可以说只有一个线程的进程有该进程的“一个”堆栈,但实际上,堆栈是线程的属性,而不是进程的属性。)但 DLL 不会“加载到进程的堆栈中”(也不会加载到线程的堆栈中)。DLL 和 EXE 被映射到进程的可共享(而非私有)虚拟地址空间中。确实,这是针对使用 DLL 或 EXE 的每个进程完成的,但这些多个实例用于虚拟内存映射。由于这是可共享的虚拟地址空间,因此 RAM 中仍然只有一个代码副本。

线程的堆栈以及堆(进程范围的内存(也称为“进程范围”)和静态存储也被映射到进程 vas 中,但与映射内存不同,它们是每个进程私有的。

相关内容