Freepascal在Windows下的每个输出上刷新stdout?

Pet*_*etr 2 windows stdout freepascal flush

看看以下四个程序.在Windows下使用Freepascal构建它们并运行,将输出重定向到任何文件,并注意它将花费的时间.

我的结果是:所有程序运行的时间大约相同(大约6秒),尽管第四个程序输出的字节数是100倍.这意味着第四个程序的每个输出字节的运行速度比其他字节的运行速度快得多.

对于第二个节目,缓慢的原因很明显:flush电话.对于第三个程序,原因并不那么明显,但假设每次调用writelnstdout都隐式刷新输出缓冲区可能是合理的.

但是,目前尚不清楚为什么第一个程序比第四个程序慢得多.然而,添加flush(output);(参见程序2)并不会改变时序的事实似乎意味着FPC甚至在每次刷新后都会刷新输出缓冲区write,这可以解释所有行为.仅当输出为stdout,甚至重定向时才会发生这种情况; 如果我使用assign/rewrite显式输出到特定文件,那么没有flush的程序运行速度比具有flush的程序要快得多 - 正如应该的那样.

在Linux下,运行时间为0.01秒,0.65秒,0.01秒,0.30秒(输出大100倍).这里显然flush()减慢程序,所以在Linux下FPC似乎不会每次刷新stdout.

我试图谷歌是否FPC真的刷新stdout缓冲区在每个输出(是它writewriteln),但没有找到任何信息,除了示例程序中的注释来自http://www.freepascal.org/docs-html的 flush函数文档/rtl/system/flush.html,评论提到a writeln到'output'总是会导致刷新[而不是write].但是,这个例子既没有在Windows下产生预期的输出,也没有在Linux下产生.实际上,输出似乎在Windows下的每次写入和写入之后刷新,重定向或不重定向,并且在输出未重定向时也在Linux下刷新.在具有重定向输出的Linux下,似乎根本没有隐式刷新.

所以,我的问题是:

  1. 在每次输出之后FPC是否刷新输出缓冲区是真的,write或者writeln在Windows上是否将输出重定向到文件?
  2. 如果是,那么有什么方法可以关闭它(一些编译器指令,或解决方法)?我仍然需要将输出保持为stdout,这样如果我启动程序没有任何重定向,它将输出文本到控制台.(我知道我可能会看到它出现在奇怪的时候,因为缓冲,这不是问题.)
  3. 如果没有,那么为什么第一个程序比第四个程序慢得多?

我的系统是在Kubuntu 14.04下的VirtualBox下使用FPC 2.6.4的Windows XP,以及使用FPC 2.6.2的Kubuntu 14.04本身.我没有机会尝试在真正的Windows机器上运行它,但我有理由相信那里的情况是一样的.


节目:

var i,j:integer;
    s:string;
begin
for j:=1 to 1000 do begin
   for i:=1 to 10 do 
      write('!');
end;
end.
Run Code Online (Sandbox Code Playgroud)
var i,j:integer;
    s:string;
begin
for j:=1 to 1000 do begin
   for i:=1 to 10 do begin
      write('!');
      flush(output);
   end;
end;
end.
Run Code Online (Sandbox Code Playgroud)
var i,j:integer;
    s:string;
begin
for j:=1 to 1000 do begin
   for i:=1 to 10 do 
      writeln('!');
end;
end.
Run Code Online (Sandbox Code Playgroud)
var i,j:integer;
    s:string;
begin
for j:=1 to 10000 do begin
   s:='';
   for i:=1 to 100 do 
      s:=s+'!';
   write(s);
end;
end.
Run Code Online (Sandbox Code Playgroud)

FPK*_*FPK 7

要防止刷新Stdout,请将以下代码段插入到您的程序中:

// Textrec is defined in sysutils
uses
  sysutils;

// ...

// disabled flushing after each write(ln) on Output, do this at the start of the program
Textrec(Output).FlushFunc:=nil;
Run Code Online (Sandbox Code Playgroud)

但请注意,这意味着在程序结束之前可能无法完成writelns.

您甚至可以通过增加stdout的输出缓冲区来进一步加速程序:

// define buffer
var
  buf : array[1..100000] of byte;

  // ...

  // install buffer, do this at the start of the program
  SetTextBuf(Output,buf,sizeof(buf));
Run Code Online (Sandbox Code Playgroud)