Посмотрите на следующие четыре программы. Создавайте их с помощью Freepascal под Windows и запускайте, перенаправляя вывод в любой файл и замечая время, которое потребуется.Freepascal flush stdout на каждом выходе под Windows?
Мои результаты: все программы работают примерно в то же время (около 6 секунд), хотя четвертый делает в 100 раз больше байтов вывода. Это означает, что четвертая программа работает намного быстрее на каждый байт вывода, чем дерево других.
Для второй программы причина медлительности очевидна: вызов flush
. Для третьей программы причина не так очевидна, но может быть разумно предположить, что каждый вызов writeln
в stdout неявно очищает выходной буфер.
Однако непонятно, почему первая программа настолько медленнее, чем четвертая. Однако тот факт, что добавление flush(output);
(см. Программу 2) не изменяет время, похоже, означает, что FPC сбрасывает выходной буфер даже после каждого write
, это объясняет все поведение. Это происходит только тогда, когда вывод выводится на stdout, даже перенаправляется; если я явно выводю в конкретный файл с помощью функции assign/rewrite, то программа без флеша работает намного быстрее, чем программа с флешем - как и следовало ожидать.
Под Linux время работы 0,01, 0,65 с 0,01 с 0,30 (выход в 100 раз больше). Здесь явно flush() замедляет программу вниз, поэтому под Linux FPC, кажется, не сбрасывает stdout каждый раз.
Я попытался Google действительно ли промывает FPC стандартный вывод буфера на каждом выходе (будь то write
или writeln
), но не нашли никакой информации, кроме комментария в примере программы из промывочной функции документации на http://www.freepascal.org/docs-html/rtl/system/flush.html, комментарий упоминает о том, что writeln
«Выход» всегда вызывает сброс [в отличие от write
]. Тем не менее, пример там не дает предполагаемого вывода ни под Windows, ни под Linux. Фактически, вывод, кажется, покраснел после каждой записи и записи в Windows, перенаправлен или нет, и под Linux тоже, когда выход не перенаправлен. В Linux с перенаправленным выходом кажется, что никакого скрытого смывания вообще нет.
Итак, мои вопросы:
- Верно ли, что FPC очищает выходной буфер после каждого выхода, будь то
write
илиwriteln
, на Windows, перенаправляется ли вывод в файл или нет? - Если да, то есть ли способ отключить это (какая-либо директива компилятора или обходной путь)? Мне все равно нужно сохранить вывод в stdout, так что, если я запустил программу без каких-либо перенаправлений, она выведет текст на консоль. (Я понимаю, что я вижу, что он появляется в странные времена в результате буферизации, это не проблема.)
- Если нет, то почему первая программа работает намного медленнее, чем четвертая?
Моя система - Windows XP с FPC 2.6.4 под VirtualBox под Kubuntu 14.04 и сама 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.
1. это правда. Просто пример: 'writeln ('наберите это'); answer: = readln; 'if writeln не очистился, а конечный пользователь перед черной консолью. Это будет добавлено даже тогда, когда i/o не перенаправляется. –
@ user3661500, я это понимаю и ожидал увидеть 'writeln', сбросив буфер, это то, о чем моя 3-я программа. Тем не менее, я был удивлен, увидев, что даже 'write' также очищает его. – Petr