如果是,我会很感激Delphi中的一个例子。
答案 0 :(得分:10)
线程本身不使用内存。进程拥有线程之间共享的内存。内存可以并且通常在一个线程中分配并在另一个线程中使用。所以你问的问题是不明确的。
那就是说,你当然可以跟踪特定线程的分配和解除分配。您可以安装一个跟踪堆分配的内存管理器,并存储在线程ID索引的字典中分配的字节数。
使用GetMemoryManager
和SetMemoryManager
将分配计数内存管理器注入运行时。想法是通过调用GetMemoryManager
来记录原始内存管理器。然后使用SetMemoryManager
替换注入内存管理器。您的内存管理器跟踪分配,并将实际分配委派给原始内存管理器。
答案 1 :(得分:9)
在Delphi中,使用Delphi的标准内存管理器(FastMM),这是不可能的。 FastMM并不关心分配哪个线程内存。
其他一些内存管理器可能提供此功能。
答案 2 :(得分:3)
看起来您可以使用ScaleMM(https://code.google.com/p/scalemm/)跟踪内存,因为它通过线程分配内存。开箱即用,它没有你需要的东西,但有些地方你可以添加它。
如果我查看代码,您可以在需要获取分配的内存量时自行遍历内存列表,或者挂钩到TThreadMemManager.GetMem,TThreadMemManager.FreeMem和TThreadMemManager.FreeMemFromOtherThread调用。此代码位于ScaleMM2.pas文件中。将记忆库添加到TThreadMemManager应该很容易,因为每个线程已经存在一个。对于另一种选择,我会查看TMediumThreadManager.ReleaseAllFreeMem中的代码,以了解它如何遍历列表。您可以执行类似的操作,并在任何时间点获取已分配RAM的列表。
要小心这一点,因为像块大小和碎片这样的东西可能意味着你会得到误导性的结果。
以下是ScaleMM2的一些更改,它们将返回每个线程的内存使用情况:
我在TThreadMemManager中添加了一个名为TotalAllocated的变量:
FSmallMemManager : TSmallMemThreadManager;
FMediumMemManager: TMediumThreadManager;
FLargeMemManager : TLargeMemThreadManager;
FTotalAllocated: Int64;
protected
然后我将以下两行添加到FreeMem的底部:
{$IFDEF SCALEMM_DEBUG}
CheckMem(nil);
{$ENDIF}
FTotalAllocated := FTotalAllocated + pm.Size;
end;
和GetMem:
{$IFDEF SCALEMM_DEBUG}
CheckMem(nil);
{$ENDIF}
FTotalAllocated := FTotalAllocated + aSize;
end;
我创建了一个名为FThreadManagerList的全局列表:
FThreadManagerList: TList<PThreadMemManager>
然后在我要检查的线程的开头,我添加了以下代码:
var
threadManager: PThreadMemManager;
begin
threadManager := GetThreadMemManager;
Synchronize(
procedure
begin
FThreadManagerList.Add(threadManager);
end);
之后,获取线程的内存就像这样简单:
for I := 0 to FThreadManagerList.Count - 1 do
begin
ListBox1.Items.Add(IntToStr(FThreadManagerList[I].FThreadID)+' : '+IntToStr(FThreadManagerList[I].FTotalAllocated));
end;
我没有查看交叉线程分配,您需要做一些研究,看看它们是如何工作的。我也没有寻找任何竞争条件,但我不认为这将是一个问题,除非你的一个线程退出。它应该给你一些东西。