简体   繁体   English

Freepascal在Windows下在每个输出上刷新标准输出吗?

[英]Freepascal flushes stdout on every output under Windows?

Look at the following four programs. 看看以下四个程序。 Build them with Freepascal under Windows and run, redirecting output to any file, and noticing the time it would take. 在Windows下使用Freepascal构建它们并运行,将输出重定向到任何文件,并注意它所花费的时间。

My results are: all the programs run approximately the same time (about 6 seconds), although the fourth does 100 times more bytes of output. 我的结果是:所有程序运行的时间大约相同(大约6秒),尽管第四个程序输出的字节数是100倍。 This means that the fourth program runs much faster per byte of output than the tree others. 这意味着第四个程序每字节输出的运行速度快于其他树。

For the second program the reason of slowness is obvious: the flush call. 对于第二个程序,缓慢的原因很明显: flush呼叫。 For the third program the reason is not so obvious, but it may be reasonable to assume that each call to writeln to stdout flushes the output buffer implicitly. 对于第三个程序,原因并不那么明显,但假设每次调用writeln到stdout都隐式刷新输出缓冲区可能是合理的。

However, it is not clear why the first program is so slower than the fourth. 但是,尚不清楚为什么第一个程序比第四个程序这么慢。 However, the fact that adding flush(output); 但是,添加flush(output);的事实flush(output); (see program 2) does not change the timing much seems to mean that FPC flushes the output buffer even after every write , this would explain all the behaviour. (参见程序2)不改变时序似乎意味着即使在每次write后FPC都会刷新输出缓冲区,这将解释所有行为。 This happens only when output is to stdout, even redirected; 仅当输出为stdout,甚至重定向时才会发生这种情况; if I explicitly output to a particular file using assign/rewrite, then the program without flush runs much faster than the program with flush — as should be expected. 如果我使用assign / rewrite显式输出到特定文件,那么没有flush的程序运行速度比具有flush的程序要快得多 - 正如应该的那样。

Under Linux the running times are 0.01s, 0.65s, 0.01s, 0.30s (output being 100 times bigger). 在Linux下,运行时间分别为0.01s,0.65s,0.01s,0.30s(输出大100倍)。 Here clearly flush() slows program down, so under Linux FPC seems not to flush stdout each time. 这里显然flush()减慢了程序,所以在Linux下FPC似乎不会每次刷新stdout。

I have tried to google whether FPC really flushes stdout buffer on every output (be it write or writeln ), but have found no information except the comment in the example program from flush function documentation at http://www.freepascal.org/docs-html/rtl/system/flush.html , the comment mentions that a writeln to 'output' always causes a flush [as opposed to write ]. 我曾尝试谷歌FPC是否真正刷新每个输出标准输出缓冲器(无论是writewriteln ),但发现除了在从冲洗功能文档示例程序的注释没有信息http://www.freepascal.org/docs -html / rtl / system / flush.html ,注释提到,'output'的writeln总是会导致刷新[而不是write ]。 However, the example there does not produce the intended output neither under Windows, neither under Linux. 但是,这个例子既没有在Windows下产生预期的输出,也没有在Linux下产生。 In fact, the output seems to be flushed after every write and writeln under Windows, redirected or not, and under Linux too when the output is not redirected. 实际上,输出似乎在Windows下的每次写入和写入之后刷新,重定向或不重定向,并且在输出未重定向时也在Linux下刷新。 Under Linux with redirected output it seems there is no implicit flushing at all. 在具有重定向输出的Linux下,似乎根本没有隐式刷新。

So, my questions are: 所以,我的问题是:

  1. Is it true that FPC flushes the output buffer after every output, be it write or writeln , on Windows whether the output is redirected to file or not? 这是真的,FPC每个输出后刷新输出缓冲区,无论是writewriteln ,Windows上的输出是否被重定向到文件或不?
  2. If yes, then is there any way to turn this off (some compiler directive, or a workaround)? 如果是,那么有什么方法可以关闭它(一些编译器指令,或解决方法)? I still need to keep the output to stdout, so that if I start the program without any redirections, it will output text to the console. 我仍然需要将输出保持为stdout,这样如果我启动程序没有任何重定向,它将输出文本到控制台。 (I understand that I might see it appearing at strange times as a result of buffering, it is not a problem.) (我知道,由于缓冲,它可能会在奇怪的时间出现,这不是问题。)
  3. If no, then why the first program runs much slower then the fourth? 如果没有,那么为什么第一个程序比第四个程序慢得多?

My system is Windows XP with FPC 2.6.4 under VirtualBox under Kubuntu 14.04, and Kubuntu 14.04 itself with FPC 2.6.2. 我的系统是在Kubuntu 14.04下的VirtualBox下使用FPC 2.6.4的Windows XP,以及使用FPC 2.6.2的Kubuntu 14.04本身。 I had no chance trying to run it on a real Windows machine, but I have some reasons to believe that the situation is the same there. 我没有机会尝试在真正的Windows机器上运行它,但我有理由相信那里的情况是一样的。


The programs: 节目:

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.

To prevent flushing of Stdout, insert the following code snippets into your program: 为防止刷新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;

But be aware that this means that writelns might not be completed before the program ends. 但是请注意,这意味着在程序结束之前可能未完成writelns。

You can even accelerate the program further by increasing the output buffer of stdout: 您甚至可以通过增加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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM