Вот скрипт, который запускает 10 процессов, каждый из которых записывает 100 000 строк в свой STDOUT, который унаследован от родителя:
#!/usr/bin/env perl
# buffer.pl
use 5.10.0;
use strict;
use warnings FATAL => "all";
use autodie;
use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new(4);
$|=1; # don't think this does anything with syswrite...
# start 10 jobs which write 100,000 lines each
for (1 .. 10 ) {
$pm->start and next;
for my $j (1 .. 100_000) {
syswrite(\*STDOUT,"$j\n");
}
$pm->finish;
}
$pm->wait_all_children;
Если я передаю канал другому процессу, все в порядке ..
$ perl buffering.pl | wc -l
1000000
Но если я передаю данные на диск, syswrites забивают друг друга.
$ perl buffering.pl > tmp.txt ; wc -l tmp.txt
457584 tmp.txt
Более того, если я открываю дескрипторы файла записи в дочерних процессах и записываю напрямую в tmp.txt:
#!/usr/bin/env perl
# buffering2.pl
use 5.10.0;
use strict;
use warnings FATAL => "all";
use autodie;
use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new(4);
$|=1;
for (1 .. 10) {
$pm->start and next;
open my $fh, '>', 'tmp.txt';
for my $j (1 .. 100_000) {
syswrite($fh,"$j\n");
}
close $fh;
$pm->finish;
}
$pm->wait_all_children;
tmp.txt содержит 1 000 000 строк, как и ожидалось.
$ perl buffering2.pl; wc -l tmp.txt
100000 tmp.txt
Так что перенаправление через '>' на диск имеет некоторую буферизацию, а перенаправление на процесс - нет?Что за сделка?