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;


Makes sense. Why the sleep(0)?
Maybe the buffersize can also be increased?


In fact if you make everything eventdriven, then you could introduce some method to mark events as thread-save, and the event-loop could automatically deploy threads, if a lot of events occur => that would be cool.

It is not clear to me why we can't check NumBytesAvailable (available since fpc 2.2.2 or earlier) on unix and windows and just forget about TAsyncProcess for compiling?

NumButesAvailable seems to block on TProcess.
From my understanding on a none blocking socket/pipe you can call all the operations like read/write/peek and they will always return immediately.
On a blocking socket they will always wait until data is there.
On a blocking socket one has to call select (fpselect), which should indicate the availabilty of data without blocking.

But Imho we should avoid sitting in a loop and sleeping.

That is what TASyncProcess.OnReadData is there fore. Read and handle all data in the event, exit the event and wait for the event to fire again. Then you can even to find in files in parallel with compiling (it wil be slow, since both access the disk) and it will work.

Martin







--
_______________________________________________
Lazarus mailing list
Lazarus@lists.lazarus.freepascal.org
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply via email to