Запись асинхронно в файл в Perl - PullRequest
8 голосов
/ 12 апреля 2010

В основном я хотел бы:

  1. Считывание большого количества данных из сети в массив в память.
  2. Асинхронно записывает данные этого массива, выполняя его через bzip2, прежде чем он попадает на диск.

повторить ..

Возможно ли это? Если это возможно, я знаю, что мне придется каким-то образом считывать следующий проход данных в другой массив, так как документы AIO говорят, что этот массив нельзя изменять до завершения асинхронной записи. Я хотел бы обработать все мои записи на диск так, чтобы проход bzip2 занял намного больше времени, чем чтение по сети.

Это выполнимо? Ниже приведен простой пример того, что, по моему мнению, необходимо, но он просто читает файл в массив @a для тестирования.

use warnings;
use strict;
use EV;
use IO::AIO;
use Compress::Bzip2;
use FileHandle;
use Fcntl;


my @a;

print "loading to array...\n";
while(<>) {
  $a[$. - 1] = $_;
}
print "array loaded...\n";


my $aio_w = EV::io IO::AIO::poll_fileno, EV::WRITE, \&IO::AIO::poll_cb;


aio_open "./out", O_WRONLY || O_NONBLOCK, 0, sub {
  my $fh = shift or die "error while opening: $!\n";

  aio_write $fh, undef, undef, $a, -1, sub {
    $_[0] > 0 or die "error: $!\n";
    EV::unloop;
  };
};

EV::loop EV::LOOP_NONBLOCK;

Ответы [ 2 ]

2 голосов
/ 09 июня 2010

Асинхронно записывать в этот массив данные

К вашему сведению, write () почти всегда асинхронны. Если, конечно, вы не заполните кэш записи ОС.

Вы бы очень мало выиграли от использования AIO по сравнению с запуском простой трубы, например, без проверки:

my $socket; # INET something
my $out = new IO::Handle;
open($out, "|bzip2 > ./out") || die;
while (1) {
  my $buf;
  $socket->recv($buf, 64*1024, 0);
  last unless defined $buf and length $buf;
  print $out $buf;
}
close($out);

В большинстве операционных систем очень трудно генерировать такое количество информации, чтобы заполнить кэш записи. Минимум - наличие bzip2 в конвейере: пропускная способность жестких дисков намного выше (> 50 МБ / с), чем производительность сжатия (в диапазоне мегабайт в секунду).

Если вы хотите запустить его в фоновом режиме или иметь несколько параллельных потоков, не бойтесь fork () и используйте exit () от child, чтобы сообщить основной программе о том, как проходила операция.

Насколько мне известно, наиболее полезный (и, вероятно, единственный полезный) аспект AIO - это асинхронное чтение. Это не может быть достигнуто любым другим способом. Использование AIO только для асинхронной записи имеет мало смысла.

0 голосов
/ 11 мая 2010

Вас может заинтересовать, как Perlbal обрабатывает подобные операции. Я считаю, что он использует Danga :: Socket для выполнения чего-то очень похожего на то, что вы хотите сделать.

...