Почему печатание "\ n" на Perl занимает так много времени? - PullRequest
9 голосов
/ 23 июня 2010

Почему печать новой строки занимает так много времени?Это только моя машина, или другие видят тот же эффект?

С новой строкой:

#!/usr/bin/perl

use strict;
use Benchmark;

   timethis(100000,'main();');


   sub main {
      print "you are the bomb. \n";
   }


   # outputs: 
   # timethis 100000:  8 wallclock secs ( 0.15 usr +  0.45 sys =  0.60 CPU) @ 166666.67/s (n=100000)

Без новой строки:

#!/usr/bin/perl

use strict;
use Benchmark;

   timethis(100000,'main();');


   sub main {
      print "you are the bomb. ";
   }


   # outputs:
   # timethis 100000:  0 wallclock secs ( 0.09 usr +  0.04 sys =  0.13 CPU) @ 769230.77/s (n=100000)
   #     (warning: too few iterations for a reliable count)

Редактировать: Я хотел бы добавить, что размещение двух "\ n" приводит к тому, что выполнение занимает вдвое больше времени, по крайней мере, для секундных часов.

timethis 100000: 16 wallclock secs ( 0.15 usr +  0.52 sys =  0.67 CPU) @ 149253.73/s (n=100000)

Ответы [ 3 ]

12 голосов
/ 23 июня 2010

Я не думаю, что буферизация имеет к этому непосредственное отношение.Я предполагаю, что это потому, что терминал должен прокручивать, когда вы печатаете новую строку (или печатаете достаточно символов, чтобы заполнить строку).Когда я сравниваю эти функции с записью в файл или /dev/null, разницы не так много.

use Benchmark;
timethis(1000000, 'main');
timethis(1000000, 'main2');
select STDERR; $| = 0; select STDOUT;  # enable buffering on STDERR
sub main { print STDERR "you are the bomb. \n" }
sub main2 { print STDERR "you are the bomb. " }

$ perl benchmark.pl 2> a_file
timethis 1000000: 21 wallclock secs ( 4.67 usr + 13.38 sys = 18.05 CPU) @ 55410.87/s
timethis 1000000: 21 wallclock secs ( 4.91 usr + 13.34 sys = 18.25 CPU) @ 54797.52/s

$ perl benchmark.pl 2> /dev/null
timethis 1000000: 26 wallclock secs ( 2.86 usr + 10.36 sys = 13.22 CPU) @ 75648.69/s
timethis 1000000: 27 wallclock secs ( 2.86 usr + 10.30 sys = 13.16 CPU) @ 76010.95/s

$ perl benchmark.pl 2> a_file     (without buffering)
timethis 1000000: 29 wallclock secs ( 3.78 usr + 12.14 sys = 15.92 CPU) @ 62806.18/s
timethis 1000000: 29 wallclock secs ( 3.27 usr + 12.51 sys = 15.78 CPU) @ 63367.34/s

$ perl benchmark.pl 2> /dev/tty   (window has 35 lines and buffers 10000, YMMV)
[ 200000 declarations of how you are a bomb deleted ]
timethis 100000: 53 wallclock secs ( 0.98 usr +  3.73 sys =  4.72 CPU) @ 21190.93/s
timethis 100000:  9 wallclock secs ( 0.36 usr +  1.94 sys =  2.30 CPU) @ 43535.05/s

Резюме: дополнительная промывка снижает производительность примерно на 10%.Дополнительная прокрутка на терминале снижает производительность примерно на 50%.

8 голосов
/ 23 июня 2010

Это не \n само по себе вызывает эту проблему.Скорее, последовательные вызовы print буферизируются ОС до тех пор, пока не встретится символ \n или не будет заполнен буфер.В этот момент выходной буфер сбрасывается на экран.Очистка вывода на экран является (относительно) дорогой операцией, поэтому цикл, в котором вы многократно очищаете выходной буфер, имеет гораздо меньшую производительность, чем цикл, в котором вы очищаете буфер только один раз в конце (что происходит неявно, когдапрограмма завершается).

3 голосов
/ 23 июня 2010

Новая строка сбрасывает вывод .

В большинстве реализаций stdio буферизация зависит от типа устройства вывода ... Последовательные устройства, , включая терминалы , модемы, мыши и джойстики, обычно имеют линейный буфер; stdio отправляет всю строку только после получения новой строки

...