windows - Freepascal 刷新 Windows 下每个输出的标准输出?

标签 windows stdout flush freepascal

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

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

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

然而,目前还不清楚为什么第一个程序比第四个程序慢那么多。然而,添加 flush(output);(见程序 2)并没有太大改变时间的事实似乎意味着即使在每次 write 之后 FPC 也会刷新输出缓冲区,这将解释所有的行为。只有当输出到标准输出,甚至重定向时,才会发生这种情况;如果我使用分配/重写显式输出到特定文件,那么不带刷新的程序运行速度比带刷新的程序快得多——正如预期的那样。

在 Linux 下,运行时间分别为 0.01 秒、0.65 秒、0.01 秒、0.30 秒(输出大 100 倍)。这里很明显 flush() 会减慢程序速度,因此在 Linux FPC 下似乎不会每次都刷新标准输出。

我尝试用谷歌搜索 FPC 是否真的在每个输出上刷新标准输出缓冲区(无论是 write 还是 writeln),但除了示例中的注释外没有找到任何信息来自 flush 函数文档的程序,位于 http://www.freepascal.org/docs-html/rtl/system/flush.html , 评论提到 writeln 到 'output' 总是导致刷新 [而不是 write]。但是,那里的示例在 Windows 和 Linux 下都不会产生预期的输出。事实上,在 Windows 下,无论是否重定向,在每次写入和写入后,输出似乎都会被刷新,而在 Linux 下,当输出未被重定向时也是如此。在具有重定向输出的 Linux 下,似乎根本没有隐式刷新。

所以,我的问题是:

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

我的系统是 Windows XP,在 Kubuntu 14.04 下的 VirtualBox 下带有 FPC 2.6.4,而 Kubuntu 14.04 本身带有 FPC 2.6.2。我没有机会尝试在真正的 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.

最佳答案

要防止刷新 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;

但请注意,这意味着写入可能不会在程序结束前完成。

您甚至可以通过增加 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));

关于windows - Freepascal 刷新 Windows 下每个输出的标准输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26948884/

相关文章:

Python stderr - 无法解析异常消息

c++ - 非阻塞 TCP 套接字并在发送后立即刷新?

c# - 如何确定我刚安装的 MSI 是否请求 Windows 重新启动?

c - 使用 printf scanf 进行 STDIN、STDOUT 重定向挂起

windows - Unix UID 与 Windows SID - 为什么?

bash - Shell 重定向 i/o 顺序

c# - 在修改 Cursor 的代码中重定向标准输出

ios - Swift 3 流委托(delegate)事件处理程序错误

windows - 批处理命令删除具有特定名称和年龄的文件夹

c++ - 如何使用 C 或 C++ 从 dll 中读取导出表?