在Perl中异步地写入文件

8

基本上,我想要:

  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;

1
aio_write 语句中的标量 $a 是一个不同于保存输入的数组 @a 的变量。 - mob
8
如果你想用 bzip 进行压缩,甚至都不需要使用 AIO。只需打开与 bzip 的管道,然后从套接字异步读取数据,并将该数据写入 bzip 管道即可。你只需要使用 AnyEvent::Handle。 - jrockway
2个回答

2

异步写入此数组数据

顺便说一下,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时:硬盘的吞吐量要高得多(>50MB/s),而压缩性能只有每秒钟几兆字节。
如果您想在后台运行它或同时运行多个流,请放心使用fork()并从子进程使用exit()来向主程序发出信号,告知操作的进行情况。
据我所知,AIO最有用(也可能是唯一有用)的方面是异步读取。这不能通过任何其他方式实现。仅使用AIO进行异步写入几乎没有意义。

0

你可能会对Perlbal如何处理这样的操作感兴趣。我相信它使用Danga::Socket来实现与你想要做的非常相似的功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接