【问题标题】:Delphi: FastMM virtual memory management reference?Delphi:FastMM 虚拟内存管理参考?
【发布时间】:2011-07-24 16:07:43
【问题描述】:

我最近遇到了一个问题(请参阅我的最后一个问题),这让我仔细研究了我的 Delphi 应用程序中的内存管理。在我第一次探索之后,我有两个问题。

我开始使用 FastMMUsageTracker,并注意到以下问题。当我打开一个应用程序使用的文件(它还创建一个表单等)时,应用程序可用虚拟内存的变化与“FastMM4 分配”内存的变化之间存在显着差异。

首先,我对术语有点困惑:为什么会有一些 FastMM 分配的内存和一些“系统分配”(和保留)的内存?既然 FastMM 是内存管理器,那为什么系统要负责分配一些内存呢?

另外,我怎样才能获得有关哪些对象/结构已分配该内存的更多详细信息? VM 图表仅用于显示“系统分配”、“系统保留”或“FastMM 分配”的内存量,但没有链接到需要该内存的实际对象。例如,是否有可能在执行过程中获得类似于 FastMM 在关闭应用程序时生成的报告? FastMM 显然将这些信息存储在某处。


作为对我的奖励,如果人们可以推荐关于该主题的良好参考资料(书籍、网站),我将不胜感激。网上有大量信息,但通常都是针对具体案例和专家的。

谢谢!

PS:这不是寻找泄漏,那里没有问题,只是试图更好地理解内存管理并为未来抢占先机,因为我们的应用程序使用越来越多的内存。

【问题讨论】:

    标签: delphi memory-management fastmm


    【解决方案1】:

    您的一些问题很简单。好吧,无论如何,其中之一!

    为什么会有一些 FastMM-allocated 内存和一些“系统分配” (和保留的)内存?由于 FastMM 是 内存管理器,为什么是系统 负责分配部分 内存?

    您在 Delphi 中编写的代码只是您的进程中运行的代码的一部分。您以 DLL 的形式使用第 3 方库,尤其是 Windows API。例如,每当您创建一个 Delphi 表单时,它背后都有很多消耗内存的 windows 对象。 FastMM 不会分配此内存,我认为这就是您的问题中所谓的“系统分配”。

    但是,如果您想更深入,那么这很快就会变成一个极其复杂的话题。如果您确实想更深入地了解 Windows 内存管理的实现,那么我认为您需要查阅一个严肃的参考资料。我建议 Mark Russinovich、David Solomon 和 Alex Ionescu 的 Windows Internals

    【讨论】:

    • 感谢 David,我认为 FastMM 会以某种方式接管所有内存分配,包括 API 调用产生的内存分配。看来我错了! :o) 我会得到那本书的副本,看看我能从中学到什么。
    【解决方案2】:

    首先,我对术语有点困惑:为什么会有一些 FastMM 分配的内存和一些“系统分配”(和保留)的内存?既然 FastMM 是内存管理器,那为什么系统要负责分配一些内存呢?

    你认为 FastMM 从哪里获得要分配的内存?当然,它来自系统。

    当您的应用启动时,FastMM 从系统获取一块内存。当您要求使用一些内存时(无论是使用 GetMem、New 还是 TSomething.Create),FastMM 会尝试从第一个初始块中将其提供给您。如果那里还不够,FastMM 会向系统请求更多(如果可能,在一个块中),并将其中的一部分返回给您。当你释放某些东西时,FastMM 不会将该内存返回给操作系统,因为它认为你会再次使用它。它只是在内部将其标记为未使用。它还尝试重新对齐未使用的块,使它们尽可能连续,以便尽量不必返回操作系统进行更多不必要的操作。 (不过,这种重新调整并不总是可能的;这就是您最终会因动态数组的多次调整大小、大量对象的创建和释放等导致内存碎片的地方。)

    除了 FastMM 在您的应用中管理的内存之外,系统还会为堆栈和堆留出空间。每个进程在启动时都会获得一兆的堆栈空间,作为放置变量的空间。这个栈(和堆)可以根据需要动态增长。

    当您的应用程序退出时,它分配的所有内存都会释放回操作系统。 (它可能不会立即出现在任务管理器中,但确实如此。)

    是否有可能在执行过程中获得类似于 FastMM 在关闭应用程序时生成的报告?

    据我所知没有。因为 FastMM 将它存储在某个地方并不一定意味着有一种方法可以在运行时从内存管理器外部访问它。您可以查看 FastMMUsageTracker 的源代码以了解如何检索信息(在 RefreshSnapshot 方法中使用 GetMemoryManagerState 和 GetMemoryMap)。 FastMM4 的源代码也可用;你可以看看有哪些公共方法可用。

    FastMM 自己的文档(以自述文件、FastMM4Options.inc cmets 和 FastMM4_FAQ.txt 文件的形式)在一定程度上有助于解释其工作原理以及可用的调试选项(和信息)。

    【讨论】:

    • 我不确定在这种情况下“系统分配”是什么意思。 if AMemoryMap[LInd] = csExSysAllocated旁边的代码中的注释说:“如果这个块不是这个MM分配的,它的状态是什么?”
    • @David,你必须拥有比我更新的 FastMM4 版本。 csExSysAllocated 不在我的 FastMM4.pas 或 UsageTracker 代码中。你引用的评论也不是。我想是时候更新了。
    • 谢谢肯。我知道 FastMM 从系统本身分配内存,但我的问题源于我错误地假设它会以某种方式处理与应用程序相关的所有内存分配,除了外部 DLL 等。我没有意识到 Windows 会接管 API 调用产生的任何内存分配。我确实开始研究 FastMM4 代码,但它非常复杂,我希望我只是错过了一个现有的功能。看来我又要跳水了! :o)
    • @Bourgui:FastMM4 无法处理由 API 调用(Windows DLL)完成的任何分配;内存必须由同一个内存管理器分配和释放,当然 Windows 本身不使用 FastMM4。 :) 操作系统以某种方式参与所有内存分配; FastMM4 只是尝试在内部为您的 Delphi 代码优化它(并且比原来的 BorlandMM 做得更好 - 这就是为什么 FastMM4 现在是默认内存管理器并由 IDE 本身使用)。
    【解决方案3】:

    有关进程使用的内存的详细地图,请尝试来自www.sysinternals.com 的 VMMAP(也由 Mark Russinovich 合着,在 David 的回答中提到)。这还允许您查看某些位置中存储的内容(选择详细信息行时键入 control-T)。

    警告:您的进程使用的内存比您想象的要多得多。您可能需要先阅读这本书。

    【讨论】:

      猜你喜欢
      • 2023-03-15
      • 2021-11-07
      • 1970-01-01
      • 2014-07-14
      • 1970-01-01
      • 2011-10-21
      • 2018-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多