[英]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.