0

我正在从另一个线程运行管道(来自 OmniThreadLibrary 的线程管道),并且出现内存泄漏或更确切地说是内存消耗。但是当应用程序关闭时就可以了,并且没有内存泄漏报告(ReportMemoryLeaksOnShutdown := True;)。

此处示例:单击按钮 10 次,测试应用程序将获得约 600 MB 的内存。Windows 7 x64,Delphi XE6,最新的全源。

这是一个错误?或者我需要使用其他代码?

uses
  OtlParallel,
  OtlCommon;

procedure TForm75.Button1Click(Sender: TObject);
begin
  // run empty pipeline from another threads
  Parallel.&For(1, 100).Execute(
    procedure(value: integer)
    var
      pipe: IOmniPipeline;
    begin
      pipe := Parallel.Pipeline
        .Stage(procedure(const input: TOmniValue; var output: TOmniValue) begin end)
        .Run;
      pipe.Cancel;
      pipe.WaitFor(100000);
      pipe := nil;
    end
  );
end;

编辑 1: 使用 ProcessExplorer 测试该代码,发现运行时线程数是恒定的,但句柄数增加了。如果我Application.ProcessMessages;在“for循环”的末尾插入(在管道代码之后)然后测试应用程序运行良好,句柄正在关闭并且内存消耗是恒定的。不知道为什么。

4

1 回答 1

0

它创建了多少个线程

例如,在 SysInternals Process Explorer 中检查它。或者在 Delphi IDE 中(查看 -> 调试窗口 -> 线程)

我认为,因为您阻止每个 For-worker 等待很长的 WaitFor 您的应用程序然后为每个按钮单击创建许多工作线程,并且当您单击它 10 次时,它会创建 10 倍的线程数。

是的,在 Windows 等通用操作系统中,线程非常昂贵!谷歌搜索“windows 线程内存占用” - 并将其乘以您生成的 10 个并行 for 循环创建的线程数。

这就是为什么要制作高度并行的服务器应用程序,需要使用特殊方法来创建轻八级应用程序级线程并绕过操作系统线程,仅举几例

然而,OTL 作为通用线程的通用库几乎没有限制,但依赖于操作系统提供的本机线程,并且它们在创建/释放 Windows 线程所需的 CPU 时间(由线程池概念缓解)和所需的内存占用方面都非常昂贵按操作系统维护每个 Windows 线程(这是不可避免的,你会看到它的表现)。

当然,稍后,当所有这些循环都完成后,它们的线程将关闭并释放,以及用于维护它们的内存。所以确实没有内存泄漏,一旦你等待足够的时间让所有线程终止 - 它们是,所有临时分配的内存都用作它们的工作场所。

UPD。如何检查该假设?最简单的方法是更改​​每个 For-Loop 实例(通过每个按钮单击)产生的线程数。

查看.NumTasksParallel.For反对的选项:

http://otl.17slon.com/book/chap04.html#leanpub-auto-iomniparallelsimpleloop-interface

默认情况下,每次单击按钮都应为每个 CPU 内核生成一个线程。但是您可以强制执行自己的线程池大小。添加.NumTasks(1)调用并检查内存消耗,然后将其签入.NumTasks(10)并再次执行。如果在那之后内存消耗会增长大约十倍 - 那么就是这样。

于 2016-04-19T15:52:11.470 回答