在perl中异步写入文件

时间:2010-04-12 00:32:01

标签: perl asynchronous io

基本上我想:

  1. 从网络中将大量数据读入内存中。
  2. 异步写入此数组数据,在它到达磁盘之前通过bzip2运行它。
  3. 重复..

    这可能吗?如果这是可能的,我知道我将不得不以某种方式读取下一个数据传递到不同的数组,因为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 个答案:

答案 0 :(得分:2)

  

异步写入此数组数据

仅供参考,write()s几乎总是异步的。除非您填写操作系统写入缓存。

与启动普通管道相比,使用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:HDD的吞吐量比压缩性能(在每秒兆字节范围内)高得多(> 50MB / s)。

如果你想在后台运行它或者并行运行几个流,不必担心fork()并使用child()从子节点向主程序发出信号,告诉你操作是如何进行的。

据我所知,AIO最有用(也可能是唯一有用)的方面是异步读取。这无法以任何其他方式实现。使用AIO只进行异步写入很有意义。

答案 1 :(得分:0)

您可能对Perlbal如何处理此类操作感兴趣。我相信它使用Danga::Socket来完成与你想要做的非常相似的事情。