FastMM:总分配内存

7

如何获取FastMM分配的总内存量?

我尝试过以下方法:

function GetTotalAllocatedMemory: Cardinal;
var
  MMState: TMemoryManagerState;
begin
  GetMemoryManagerState(MMState);
  Result := MMState.TotalAllocatedMediumBlockSize + MMState.TotalAllocatedLargeBlockSize;
end;

这是否正确?

无论如何,它返回了一些奇怪的东西。它比我在Windows任务管理器中看到的值少5倍。我相信Delphi应用程序分配的内存量等于FastMM分配的内存量加上一些系统开销。我错了吗?


你是在与任务管理器中的哪一列进行GetTotalAllocatedMemory的结果比较,Cosmin 是指哪一列? - Remko
截图 :) http://img41.imageshack.us/img41/779/26301229.png - Roman Yankovsky
在我的Win 7和Windows 2008服务器的任务管理器中甚至没有“内存使用”列。我有大约9个不同的列来处理内存使用的不同方面及其动态。我猜旧的Win XP“内存使用”信息量如此之大,以至于它们完全放弃了它。 - Cosmin Prund
我会使用Sysinternals的VMMap和RAMMap来检查内存使用情况,而不是任务管理器。它们提供了更详细的信息。 - user160694
3
请给我一分钟时间考虑一下:假设FastMM使用跟踪器包含了FastMM作者认为报告使用情况的正确方式的源代码。如果你想知道如何正确地做,那么我认为没有比这更好的信息来源了。 - David Heffernan
显示剩余7条评论
4个回答

4
请使用以下内容:
//------------------------------------------------------------------------------  
// CsiGetApplicationMemory  
//  
// Returns the amount of memory used by the application (does not include  
// reserved memory)  
//------------------------------------------------------------------------------  
function CsiGetApplicationMemory: Int64;  
var  
  lMemoryState: TMemoryManagerState;  
  lIndex: Integer;  
begin  
  Result := 0;  

  // get the state  
  GetMemoryManagerState(lMemoryState);  

  with lMemoryState do begin  
    // small blocks  
    for lIndex := Low(SmallBlockTypeStates) to High(SmallBlockTypeStates) do  
      Inc(Result,  
          SmallBlockTypeStates[lIndex].AllocatedBlockCount *  
          SmallBlockTypeStates[lIndex].UseableBlockSize);  

    // medium blocks  
    Inc(Result, TotalAllocatedMediumBlockSize);  

    // large blocks  
    Inc(Result, TotalAllocatedLargeBlockSize);  
  end;  
end;

顺便提一下,这将只给出FastMM分配的内存。请参阅另一个答案以获取进程内存使用情况。 - Misha

4

你在比较苹果和橙子。

FastMM内存是通过FastMM分配的内存的净使用量。

这里至少不包括以下内容:

  • FastMM开销
  • 由FastMM代表您分配的块的Windows开销
  • 未由FastMM分配的东西(例如DLL在进程空间中占用的空间)的Windows开销
  • 对于GUI应用程序:GDI、GDI+、DirectX、OpenGL和其他为您分配的可视对象的存储的开销。

--jeroen


你忘记了最大的一部分,即Windows拥有的内存、GDI对象等。 - David Heffernan
这取决于你的应用程序是否是图形用户界面(GUI)。;-》 - Jeroen Wiert Pluimers

3

如果要使用进程内存,请使用以下方法:

//------------------------------------------------------------------------------
// CsiGetProcessMemory
//
// Return the amount of memory used by the process
//------------------------------------------------------------------------------
function CsiGetProcessMemory: Int64;
var
  lMemoryCounters: TProcessMemoryCounters;
  lSize: Integer;
begin
  lSize := SizeOf(lMemoryCounters);
  FillChar(lMemoryCounters, lSize, 0);
  if GetProcessMemoryInfo(CsiGetProcessHandle, @lMemoryCounters, lSize) then
    Result := lMemoryCounters.PageFileUsage
  else
    Result := 0;
end;

1
CsiGetProcessHandle是做什么的? - Roman Yankovsky
一个封装了Windows API调用GetCurrentProcess的包装器。 - Misha
1
-1 是因为PageFileUsage不是当前的内存使用情况。请参阅http://blogs.technet.com/b/perfguru/archive/2008/01/08/explanation-of-pagefile-usage-as-reported-in-the-task-manager.aspx。 - Arnaud Bouchez
@A.Bouchez,仅仅说出它不是而不列举替代方案有点懒。 - Misha

3

我也遇到过这种情况:

无论如何,它返回了一些奇怪的东西。它比我在Windows任务管理器中看到的值小了5倍。我相信Delphi应用程序分配的内存量等于FastMM分配的内存量加上一些系统开销。我错了吗?

我浪费了好几个小时,试图找出所有的内存去向。根据任务管理器,我的应用程序占用了170 MB的空间,但是FastMM的统计数据显示已分配块的总大小只有约13 MB:

12565K Allocated
160840K Overhead
7% Efficiency

(FastMM LogMemoryManagerStateToFile过程输出摘录)。最后我意识到,这种巨大的开销是由于FullDebug模式引起的。它为每个分配保留堆栈跟踪,因此如果您分配了许多微小的内存块(我的应用程序有UnicodeString x 99137、Unknown x 17014和约10000个Xml对象),那么开销会变得令人惊恐。去除FullDebug模式将内存消耗恢复到正常值。
希望这能帮助某些人。

当移除FullDebug模式时,您会得到什么样的效率?我从5%提高到了16%,但在我看来仍然无法接受... - Jaap Versteegh
@SlashV 我得到了1627K分配,4771K开销,25%效率。我不知道它是否好,因为我有很多小的内存块在那里,其中包括617652字节:TXmlAttr x 7353(平均84字节),429708字节:UnicodeString x 9315(平均46字节),190860字节:Unknown x 2861(平均66字节),161704字节:TXmlElement x 1394(平均116字节),62972字节:TXmlAttrList x 1211(平均52字节),这显然是一个效率难题。 - Fr0sT
我发现我的低效率只是由于内存被释放但未返回给操作系统。即在我查看整体使用情况之前,临时对象已被创建和释放。 - Jaap Versteegh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接