.net - DLL、内存映射、基地址、内存使用和 .NET?

标签 .net memory dll base-address

在我开始真正的问题之前,让我先说一下我可能会弄错这里的一些细节。如果是这样,请在这些问题上逮捕我,甚至不要回答我的问题。

我的问题基本上是关于 DLL 和 .NET。我们有一个使用大量内存的应用程序,我们正试图弄清楚如何正确测量这一点,尤其是当问题主要发生在客户的计算机上时。

让我印象深刻的一件事是,我们有一些相当大的 .NET 程序集,其中包含生成的 ORM 代码。

如果我使用具有唯一基地址的非托管 (Win32) DLL,同一台机器上的多个同时进程会将 DLL 加载到物理内存中,然后将其映射到所有应用程序的虚拟内存中。因此,此 DLL 将使用一次物理内存。

问题是 .NET 程序集会发生什么。这个 DLL 包含 IL,虽然它的这一部分可能在应用程序之间共享,但是由这个 IL 产生的 JITted 代码呢?是共享的吗?如果不是,我如何衡量以找出这实际上是否导致了问题? (是的,我知道,它会有所贡献,但我不会花太多时间在这上面,直到它成为最大的问题)。

另外,我知道我们还没有查看解决方案中所有 .NET 程序集的基地址,.NET 程序集是否有必要这样做?如果是这样,是否有一些关于如何确定这些地址的指南?

欢迎对此领域的任何见解,即使事实证明这不是一个大问题,甚至根本不是问题。


编辑:刚刚发现这个问题:.NET assemblies and DLL rebasing这部分回答了我的问题,但我仍然想知道 JITted 代码是如何影响所有这些的。

从该问题及其接受的答案看来,JITted 代码放置在堆上,这意味着每个进程将加载共享二进制程序集镜像,并在其自己的内存空间中生成代码的私有(private) JITted 副本.

我们有什么方法可以衡量这个吗?如果结果证明这会产生大量代码,我们将不得不更多地查看生成的代码以确定是否需要对其进行调整。


编辑:在此处添加了较短的问题列表:

  1. 确保 .NET 程序集的基地址是唯一的且不重叠以避免重新设置主要用于将 IL 代码从 JITting 中提取出来的 dll 是否有任何意义?
  2. 如何衡量 JITted 代码使用了多少内存来确定这是否真的是一个问题?

@Brian Rasmussen 的回答here表明 JITting 将生成 JITted 代码的每个进程副本,正如我所料,但重新设置程序集实际上会对减少内存使用产生影响。我将不得不深入研究他提到的 WinDbg+SoS 工具,我已经在我的列表中列出了一段时间,但现在我怀疑我不能再推迟了 :)


编辑:我在该主题上找到了一些链接:

最佳答案

这是针对问题 1)

jit 代码被放置在一个特殊的堆上。您可以使用 WinDbg + SoS 中的 !eeheap 命令检查此堆。因此,每个进程都将拥有自己的 jitted 代码副本。该命令还将显示代码堆的总大小。

如果您想了解有关从 WinDbg 获取此信息的更多详细信息,请告诉我。

这是针对问题 2)

根据Expert .NET 2.0 IL Assembly一书,纯IL PE 文件的.reloc 部分仅包含一个用于CLR 启动 stub 的修复条目。因此,在 rebase 期间托管 DLL 所需的修复量是相当有限的。

但是,如果您列出任何给定的托管进程,您会注意到 Microsoft 已重新设置其托管 DLL 的大部分(或全部)基础。是否应将其视为 rebase 的原因取决于您。

关于.net - DLL、内存映射、基地址、内存使用和 .NET?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/479146/

相关文章:

c++ - 使用 DLL 写入文件

C# .NET 将 InterfaceImplementingClass 对象的集合传递给采用接口(interface)对象集合的例程

c++ - 添加路径到 DLL 搜索路径以帮助执行依赖于 DLL 的 EXE

c# - 在没有回发的情况下重置 ASP.NET 中的页面

ios - Xcode - 我的应用程序崩溃,错误是 "Invalid pointer dequeued from free list *** set a breakpoint in malloc_error_break to debug"

c++ - 函数返回的神秘段错误,不涉及指针或分配

php - 教义刷新更改并释放内存

c - 屏幕保护程序依赖于文件 C

c# - 在 .NET 中使用 Firebase

c# - .NET Framework 类的 Unity 最佳实践