2010-04-12 148 views
8

到文件基本上我想:异步写在Perl

  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 2010-04-12 04:41:20

+8

如果你正在写bzip进行压缩,你甚至不需要AIO。打开一个管道到bzip,然后从套接字读取(异步)并将该数据写入bzip管道。 AnyEvent :: Handle是你所需要的。 – jrockway 2010-04-12 08:49:06

回答

0

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

2

异步写入这个数组数据

FYI,写()s为几乎总是异步的。除非你填写OS写缓存。

您会获得很少使用的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(),并使用子节点的exit()来告诉主程序操作是如何进行的。

据我所知,AIO最有用的(也许只是有用的)方面是异步读取。这是无法用其他方式实现的。使用AIO只进行异步写入几乎没有意义。