gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 02:25:20 26 4
gpt4 key购买 nike

从 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 的文档声明文件确实被使用

Captures are normally done to an anonymous temporary filehandle.



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

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

To capture via a named file (e.g. to externally monitor a long-running capture), provide custom filehandles as a trailing list of option pairs:

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;

The filehandles must be read/write and seekable. Modifying the files or filehandles during a capture operation will give unpredictable results. Existing IO layers on them may be changed by the capture.



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

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

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

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

† 粗略的草图

所有方法的“分派(dispatch)”到 _capture_tee完成 in the beginning ,其中一组标志是 unshift编辑到 @_之前 goto &func把它拿走,以区分方法。对于 capture这是 1,1,0,0 , 什么设置变量 $do_stdout$do_stderr_capture_tee .然后这些用于设置 %do hash , 哪些键是 iterated over to set up $stash .

如果额外的参数被传递给 capture (对于命名文件)然后 $stash->{capture} is set ,否则为 File::Temp对象被赋值。 $stash稍后 passed to _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():在 ... 处重定向 STDOUT 的参数无效

这是因为 open到标量不会设置真正的文件句柄。见 this post .

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

关于perl - Perl 的 Capture::Tiny::capture() 是否避免了使用 system() 时需要的磁盘 io?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49536450/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com