簡體   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