【问题标题】:Write asynchronously to file in perl在 perl 中异步写入文件
【发布时间】:2011-02-06 20:06:37
【问题描述】:

基本上我想:

  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;

【问题讨论】:

  • aio_write 语句中的标量 $a 与保存输入的数组 @a 不同。
  • 如果您正在写入 bzip 进行压缩,您甚至不需要 AIO。打开到 bzip 的管道,然后从套接字(异步)读取并将该数据写入 bzip 管道。 AnyEvent::Handle 就是你所需要的。

标签: perl asynchronous io


【解决方案1】:

异步写入这个数组数据

仅供参考,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 的情况最少:HDD 的吞吐量(>50MB/s)远高于压缩性能(以兆字节/秒为单位)。

如果你想在后台运行它或有多个并行流,不用担心 fork() 并使用子程序的 exit() 来通知主程序操作是如何进行的。

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2017-06-07
      • 1970-01-01
      • 1970-01-01
      • 2012-08-31
      • 1970-01-01
      • 2012-09-26
      • 1970-01-01
      相关资源
      最近更新 更多