繁体   English   中英

Perl 的 Capture::Tiny::capture() 是否避免使用 system() 时需要磁盘 io?

[英]does Perl's Capture::Tiny::capture() avoid disk io required when using system()?

从 Perl 脚本调用外部程序时,Capture::Tiny 是否避免使用 system() 时需要磁盘 io? 使用两者时,我获得的性能基本相同。 一位同事正在使用我的代码并告诉我它正在锤击他的磁盘。 在我的本地机器上运行并写入本地磁盘时,我(也许)没有这个问题。

我以前是这样做的:

open($fhStdin, ">stdin.txt");
print $fhStdin "some text\n";
close($fhStdin);
system("cmd < stdin.txt 1> stdout.txt 2> stderr.txt"); 
# open and read stdout.txt
# open and read stderr.txt

并改为:

($stdout, $stderr, $exit) = capture {
    open($fhStdin, '| cmd');
    print $fhStdin "some text\n";
    close($fhStdin);
};

但 NYTProf 告诉我,它们运行所需的时间基本上相同(但 NYTProf 从子例程时间中删除了磁盘 io 开销)。 所以我想知道 capture() 是否正在写入引擎盖下的临时文件? (我尝试阅读 Tiny.pm 源代码,但很惭愧地说我无法从中分辨出来。)

感谢您提供任何提示。

Capture::Tiny::capture的文档指出确实使用了文件

捕获通常是对匿名临时文件句柄进行的。

这可以在_capture_tee子的源代码中看到,用作所有方法的通用例程。 大约进行到一半时,我们发现调用File::Temp->new发生,除非要使用命名文件(见下文)。 可以小心地跟踪其余的处理过程。

文档继续提供一种通过命名文件来监视所有这些的方法

要通过命名文件进行捕获(例如从外部监视长时间运行的捕获),请提供自定义文件句柄作为选项对的尾随列表:

 my $out_fh = IO::File->new("out.txt", "w+"); my $err_fh = IO::File->new("out.txt", "w+"); capture { ... } stdout => $out_fh, stderr => $err_fh;

文件句柄必须是读/写和可查找的。 在捕获操作期间修改文件或文件句柄将产生不可预测的结果。 捕获可能会更改它们上现有的 IO 层。

(如果这样做,那么对File::Temp的调用将不会进行,如上所述。请参阅源代码。)

如果此磁盘活动有问题,您可以使用管道打开读取cmd的输出(首先将其输入写入文件),或使用qx (反引号)。 但是你必须合并或重定向STDERR并通过更多的箍来检查和处理错误。

另一种选择是使用IPC::Run3 虽然它也使用文件,但它提供了更多的选项,可以用来减少磁盘 I/O,或者可能完全避免使用磁盘。 (使用打开为标量(内存中)的文件句柄进行调用的想法不起作用,因为这不是真正的文件句柄。

“核”选项是更复杂的IPC::Run ,它可以在不使用磁盘的情况下进行输出。


粗略的草图

将所有方法“调度”到_capture_tee在开始时完成,在goto &func将其带走之前,一组标志被unshift ed 到@_ ,以区分方法。 对于capture这是1,1,0,0 ,它在1,1,0,0设置变量$do_stdout$do_stderr _capture_tee 然后使用这些来设置%do哈希,这些键被迭代以设置$stash

如果将额外的参数传递给capture (对于命名文件),则设置$stash->{capture} ,否则分配File::Temp对象。 $stash稍后会传递给发生重定向的_open_std

还有更多,但主要与本地化球体和图层的操作有关。


最常见的调用写入标量

run3 \@cmd, \my $in, \my $out, \my $err;

但这使用文件,如How it works下的文档中所述。

试图通过写入打开为标量的文件句柄来欺骗它不使用文件

my @cmd = qw(ls -l .);
open my $fh, '>', \my $cmd_out;  # not a real filehandle ...
run3 \@cmd, \undef, $fh;         # ... so this won't work

中止

run3(): Invalid argument redirecting STDOUT at ...

这是因为对标量的open不会设置真正的文件句柄。 看到这个帖子

如果文件句柄被打开到一个文件,这将按预期工作,写入该文件。 Capture::Tiny相比,这可能会导致更高效的磁盘 I/O 操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM