2013-03-14 226 views
10

我想了解這兩個類似命令之間的差異。命令替換vs進程替換

aa=$(foo | bar | head -1) 
read aa < <(foo | bar | head -1) 
  • 我知道<()需要#!/bin/bash,但它使得它更慢?
  • 他們是否創造了相同數量的亞殼?
  • 他們是否需要相同數量的bashsh流程?

我正在尋找使用最佳性能的命令。

回答

6
  1. 號擊是在非POSIX模式快。
  2. 這取決於。這既是實現特定的,也是特定於平臺的細節。
    • 在Bash中,兩者都需要相同數量的進程。如果沒有啓用lastpipe,則每個管道元素都有一個進程,並且有一個用於替換加上父進程的子shell。
    • 在bash,如果lastpipe啓用,該管道將exec的不分叉在這兩種情況下,仍然需要相同數量的進程的最後一個元素。
    • 在ksh93的,都應該要求相同數量的在這種情況下的過程,但如果最後的管道元素是一個內置的,它會在父的命令替換的過程中運行,使之更快。
    • 在這兩個Bash和ksh93的,如果shell不支持/dev/fd/*的系統上編譯,外殼將創建一個名爲工藝替代管道代替。這可能會影響性能。
  3. 以前的子彈或許應該去這裏。注意:「subshel​​l」並不一定意味着一個單獨的進程,儘管在幾乎所有的shell中它都會(除了支持Bash的其他所有東西外,其他都是$(<...))。在mksh和ksh93中,還有${ ;}樣式命令替換,但每個shell都以不同的方式實現它。在ksh93中,它可能會或可能不會加速。在mksh中,可能不是。 mksh不支持進程替換,並且zsh不支持(並且無法模擬)BASHPID,所以我沒有研究它。

沒有什麼本質上快約比猛砸一個進程替換命令替換,但head是在read的情況下,多餘的,因爲你只是讀一行在那裏。順便說一句,總是使用head -n ... - -1是不便攜的。另外,除非您希望外殼破壞輸入,否則不要使用read而不使用-r

2

Benchmarking與Bash's內置time,第一種形式比第二種形式慢。

你可以測試它自己:

bash -c 'time PIPELINE...' 

兩個創建子shell - 從背景殼閱讀和擴大其在第一種情況下一個子shell的輸出,與外殼的read內置閱讀第二個過程。

參見:

+1

嗯,這個說法並不完全正確。希望你不介意我已經爲你調整了一下。在這兩種情況下都有「文件描述符」,並且兩者都會生成一個子shell,至少在Bash中也總是暗含至少一個分支。在我的更廣泛的測試中,「read -rx <(...)'」和「'x = $(...)'」之間的區別幾乎無法用小輸入迭代,對於單個大輸入,分配的速度稍快(與預期的一樣),但在最初的問題中,兩種解決方案都是奇數和次優的。 – ormaaj 2013-03-14 20:48:45

+0

沒問題'兄弟,感謝編輯。 – 2013-03-15 00:31:14

1

在這裏提高性能的最佳方式是讓儘可能多的,你可以擺脫叉子和管道。

對於所有意圖和目的,您不應該擔心所述的性能問題。執行時間的99%很可能由特定命令決定,而不是過程替換與命令替換之間的差異。你知道優化的第一個規律嗎?別。尤其是如果你犧牲可移植性。使用$(whatever)並忘記其他所有內容。如果您真的擔心性能問題,那就是您需要解決的命令/管道/分支。否則,你試圖通過擠壓眼淚來減肥。

1

進程替換繞過了由管道/命令替換創建的子shell。替換語法被替換爲FIFO或FD的名稱,其中的命令在後臺運行。 替代作爲參數擴展和命令替換同時執行

查看與「tee」一起使用的過程替換信息。

http://mywiki.wooledge.org/ProcessSubstitution