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

时间:2014-11-15 17:54:10

标签: windows stdout flush freepascal

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

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

对于第二个程序,缓慢的原因很明显:flush调用。对于第三个程序,原因并不那么明显,但可以合理地假设每次调用writeln到stdout都会隐式刷新输出缓冲区。

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

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

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

所以,我的问题是:

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

    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.
    

    var i,j:integer;
        s:string;
    begin
    for j:=1 to 1000 do begin
       for i:=1 to 10 do 
          writeln('!');
    end;
    end.
    

    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.
    

1 个答案:

答案 0 :(得分: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;

但请注意,这意味着在程序结束之前可能无法完成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));