Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 我可以测量线程的实际内存使用情况吗?_Multithreading_Delphi_Memory - Fatal编程技术网

Multithreading 我可以测量线程的实际内存使用情况吗?

Multithreading 我可以测量线程的实际内存使用情况吗?,multithreading,delphi,memory,Multithreading,Delphi,Memory,如果是的话,我想举一个德尔菲的例子 我已经尝试在Delphi中使用和,使用Delphi的标准内存管理器(FastMM),这是不可能的。FastMM不关心从哪个线程分配内存 其他一些内存管理器可能提供此功能 线程本身不使用内存。进程拥有线程之间共享的内存。内存可以,而且经常在一个线程中分配,在另一个线程中使用。所以你问的问题是不明确的 也就是说,您当然可以跟踪特定线程进行的分配和解除分配。您可以安装一个内存管理器来跟踪堆分配,并将分配的字节数存储在一个根据线程ID编制索引的字典中 使用GetMem

如果是的话,我想举一个德尔菲的例子


我已经尝试在Delphi中使用和,使用Delphi的标准内存管理器(FastMM),这是不可能的。FastMM不关心从哪个线程分配内存


其他一些内存管理器可能提供此功能

线程本身不使用内存。进程拥有线程之间共享的内存。内存可以,而且经常在一个线程中分配,在另一个线程中使用。所以你问的问题是不明确的

也就是说,您当然可以跟踪特定线程进行的分配和解除分配。您可以安装一个内存管理器来跟踪堆分配,并将分配的字节数存储在一个根据线程ID编制索引的字典中


使用
GetMemoryManager
SetMemoryManager
将分配计数内存管理器注入运行时。其思想是通过调用
GetMemoryManager
来记录原始内存管理器。然后使用
SetMemoryManager
替换内存管理器。内存管理器跟踪分配,并将实际分配委托给原始内存管理器

看起来您将能够使用ScaleMM()跟踪内存,因为它按线程分配内存。开箱即用,它没有你需要的东西,但有些地方你可以添加它

如果我看一下代码,您可以在需要获得分配的内存量时自行查看内存列表,或者挂接到TThreadMemManager.GetMem、TThreadMemManager.FreeMem和TThreadMemManager.freemfromOtherThread调用。此代码位于scalem2.pas文件中。将memcount添加到TThreadMemManager应该很容易,因为每个线程已经有一个memcount。对于另一个备选方案,我将查看TMediumThreadManager.ReleaseAllFreeMem中的代码,以了解它如何处理列表。您可以执行类似的操作,并在任何时间点获得分配的RAM列表

要小心一点,因为块大小和碎片可能会导致误导性结果

下面是对ScaleM2的一些更改,这些更改将返回每个线程的内存使用情况:

我向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>
之后,获取线程的内存就这么简单:

for I := 0 to FThreadManagerList.Count - 1 do
begin
  ListBox1.Items.Add(IntToStr(FThreadManagerList[I].FThreadID)+' : '+IntToStr(FThreadManagerList[I].FTotalAllocated));
end;

我没有研究跨线程分配,您需要做一些研究,看看它们是如何工作的。我也没有寻找任何比赛条件,但我不认为这将是一个问题,除非你的线程之一退出。它应该会给你一些开始的东西。

你能扩展一下你所说的按线程分配内存的意思吗。你是说这样的内存对分配线程来说是私有的吗?这听起来难以置信。那么你的意思是什么?@DavidHeffernan ScaleMM所做的就是每个线程有一个不同的内存管理器。每次线程请求内存缩放时,EMM都会去获取该线程的内存管理器,然后使用该管理器请求内存。它们有一些处理跨线程释放的逻辑,等等。我没有使用该库,但它应该可以帮助OP跟踪每个线程的内存。@DavidHeffernan它不是真正私有的。显然,内存是作为一个整体分配给进程的。ScaleMM所做的是在内部跟踪分配内存的线程。我在ScaleMM 2中创建了一个事件侦听器,尝试了这个解决方案,但没有成功,因为我需要创建一个列表来跟踪线程,此Create调用再次调用GetMem创建无限递归。@MarceloGimenes您不需要创建和事件侦听器或列表。我添加了一些用于一些基本测试的代码。
for I := 0 to FThreadManagerList.Count - 1 do
begin
  ListBox1.Items.Add(IntToStr(FThreadManagerList[I].FThreadID)+' : '+IntToStr(FThreadManagerList[I].FTotalAllocated));
end;