[Lazarus] Multi-threading support in IDE
Martin
lazarus at mfriebe.de
Fri Aug 14 18:21:51 CEST 2009
The loop in outputfilter can be simplified quite a bit
All the extra handling of the asyncprocess can be reduced to the
following lines (the event handlers can be removed):
if fProcess is TAsyncProcess then begin
Count:=TAsyncProcess(fProcess).NumBytesAvailable;
if Count > 0 then
Count:=fProcess.Output.Read(Buf[1], Min(Count, length(Buf)));
end
else
// using a blocking TProcess
Count:=fProcess.Output.Read(Buf[1], length(Buf));
if (Count=0) and (not fProcess.Running) then
break
else if count = 0 then
sleep(30);
Works on windows / shouldn't change anything on *nix
Martin wrote:
> Vincent Snijders wrote:
>> I have looked a bit more why outputfilter is so slow at parsing a lot
>> of compiler output (e.g. compiling a simple LCL app with -va). The
>> pipe buffer is rather small, NumBytesAvailable is not bigger than
>> 1280 bytes. So OnAsyncReadData reads only 1280 bytes at a time.
>> OnAsyncReadData is only called after an application.handlemessage. So
>> on line 319 of outputfilter.pas, the buffer is most times empty, but
>> NumBytesAvailable = 1280, and we are sleeping until
>> Application.HandleMessage is called.
>>
>> I had some success with the following patch. It does a sleep(0) to
>> give the compiler the chance to write to the pipe again and tries to
>> read it again.
>> --- ide/outputfilter.pas
>> +++ ide/outputfilter.pas
>> @@ -1206,9 +1206,12 @@ var
>> Count: LongWord;
>> begin
>> if fProcess=nil then exit;
>> - Count:=TAsyncProcess(fProcess).NumBytesAvailable;
>> - if Count>0 then
>> - FAsyncOutput.Push(TStream(TAsyncProcess(fProcess).Output),Count);
>> + repeat
>> + Count:=TAsyncProcess(fProcess).NumBytesAvailable;
>> + if Count>0 then
>> + FAsyncOutput.Push(TStream(TAsyncProcess(fProcess).Output),Count);
>> + sleep(0);
>> + until Count=0;
>> end;
>>
>> function TOutputFilter.CreateScanners(ScannerOptions: TStrings):
>> boolean;
> If I understand it correctly the problem is that TAsyncProcess,
> currently only reads data, when the event is triggered, which is in a
> ProcessMessages. Ouch.
>
> Either TAsyncProcess.OnReadData is transferred into the main loop, in
> a similar way as for the normal TProcess.
> I have not tested this, but it should work, as NumBytesAvailable seems
> to be none blocking.
> => This could simplify the overall loop as the handling of the 2
> projects would be more or less the same.
>
> Alternatively, before we sleep(3), we could check for data, and
> process it.
> end else begin
> // no new input, but process still running
> if TheAsyncProcess.NumBytesAvailable > 0 then
> Application.ProcessMessages
> else
> Sleep(30);
> end;
>
>
>
> --
> _______________________________________________
> Lazarus mailing list
> Lazarus at lists.lazarus.freepascal.org
> http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
More information about the Lazarus
mailing list