我从另一个线程运行管道(来自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测试了代码,发现运行时线程计数是常数的,但是句柄计数是增长的。如果我在"for循环“的末尾插入Application.ProcessMessages; (在管道的代码之后),那么测试应用程序运行良好,句柄关闭,内存消耗是恒定的。不知道为什么。
发布于 2016-04-19 15:52:11
它创建了多少个线程?
例如,在SysInternals Process中检查它。或者在Delphi中(查看->调试->线程)
我认为,因为您为一个长WaitFor阻塞了每个工作线程,所以您的应用程序会为每个按钮单击创建许多工作线程,而当您单击它10次时,它将创建10倍多的线程。
是的,像Windows线程这样的通用操作系统是昂贵的!谷歌为"windows线程内存足迹“--并乘以10个并行创建的线程数量-为您生成的循环。
这就是为什么为了使高度并行的服务器应用程序能够创建轻8个应用程序级线程和绕过OS线程的特殊方法,举几个例子。
然而,作为泛型线程的通用库,OTL对一般线程的限制很小,但依赖于OS提供的本机线程,在创建/释放Windows线程所需的CPU时间(通过线程池概念减轻)和通过OS维护每个Windows线程所需的内存占用(这是不可避免的,并且您可以看到其表现形式)方面,OTL都很昂贵。
当然,当所有这些循环都通过时,它们的线程将被关闭并释放,以及用于维护它们的内存。因此,一旦您等待足够多的线程终止,就不会有内存泄漏--它们是的,所有临时分配的内存都用作它们的工作位置。
UPD。如何验证这一假设?最简单的方法是更改For-循环的每个实例(每次单击按钮)产生了多少线程。
请参阅您的.NumTasks对象的Parallel.For选项:
http://otl.17slon.com/book/chap04.html#leanpub-auto-iomniparallelsimpleloop-interface
默认情况下,每个按钮单击都应该为每个CPU核心生成一个线程。但是,您可以强制执行自己的线程池大小。添加.NumTasks(1)调用并检查内存消耗,然后将其签入.NumTasks(10)并再次执行。如果在那之后,内存消耗会增长大约十倍,那么就是它了。
https://stackoverflow.com/questions/36711681
复制相似问题