从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
Run Code Online (Sandbox Code Playgroud)
并更改为:
($stdout, $stderr, $exit) = capture {
open($fhStdin, '| cmd');
print $fhStdin "some text\n";
close($fhStdin);
};
Run Code Online (Sandbox Code Playgroud)
但是NYTProf告诉我,它们花费的时间基本上相同(但是NYTProf消除了子例程时间的磁盘io开销)。所以我想知道capture()是否在后台写入临时文件?(我尝试阅读Tiny.pm源代码,但感到羞耻地说我无法分辨。)
感谢您的提示。
Capture :: Tiny :: capture的文档 指出确实使用了文件
捕获通常是对匿名临时文件句柄进行的。
可以在_capture_tee子代码的源代码中看到它,用作所有方法的通用例程。除非使用命名文件,否则在此子程序的大约一半处,我们会找到发生的调用File::Temp->new(请参见下文)。可以仔细跟踪其余的处理过程。†
文档继续提供一种通过命名文件监视所有这些内容的方法
要通过命名文件进行捕获(例如,从外部监视长时间运行的捕获),请提供自定义文件句柄作为选项对的尾随列表:
Run Code Online (Sandbox Code Playgroud)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都是在开始时完成的,在开始之前对一组标志进行了unshift编辑,以带走它们以区分方法。对于这个,有什么设置变量,并在。然后使用它们来建立哈希,然后将其迭代遍历以建立哈希。@_goto &funccapture1,1,0,0$do_stdout$do_stderr_capture_tee%do$stash
如果将额外的参数传递给capture(用于命名文件),那么$stash->{capture}将设置set,否则File::Temp分配一个对象。在$stash随后传递到_open_std重定向发生在哪里。
还有很多,但主要与本地glob和图层的操纵有关。
‡ 最常见的调用写入标量
run3 \@cmd, \my $in, \my $out, \my $err;
Run Code Online (Sandbox Code Playgroud)
但这会使用文件,如docs下的工作原理中所述。
试图通过写一个打开到标量的文件句柄来欺骗它不使用文件
my @cmd = qw(ls -l .);
open my $fh, '>', \my $cmd_out; # not a real filehandle ...
run3 \@cmd, \undef, $fh; # ... so this won't work
Run Code Online (Sandbox Code Playgroud)
中止
run3():无效的参数将STDOUT重定向到...
这是因为open到标量并没有设置实际的文件句柄。看到这篇文章。
如果文件句柄已打开到文件,则该文件将按预期工作,并写入该文件。与之相比,这很可能导致更高效的磁盘I / O操作Capture::Tiny。
| 归档时间: |
|
| 查看次数: |
93 次 |
| 最近记录: |