2016-11-26 147 views
1

我正在使用Node.js產生100個以上的子進程,可能甚至是1000.我關心的是父進程可能會成爲某種瓶頸如果所有的子進程的stdout/stderr必須通過父進程才能在某處登錄。從父進程派生/產生許多node.js進程的最高性能方式

所以我的假設是,爲了達到最高的性能/吞吐量,我們應在父進程忽略標準輸出/標準錯誤,就像這樣:

const cp = require('child_process'); 

items.forEach(function(exec){ 

    const n = cp.spawn('node', [exec], { 
     stdio: ['ignore','ignore','ignore','ipc'] 
    }); 

}); 

我的問題是,如何在性能損失的錢它以這種方式使用管道:

// (100+ items to iterate over) 

items.forEach(function(exec){ 

    const n = cp.spawn('node', [exec], { 
     stdio: ['ignore','pipe','pipe','ipc'] 
    }); 

}); 

這樣,stdout和stderr被傳送到父進程?我假設的性能損失可能是激烈的,特別是如果我們處理標準輸出/標準錯誤在父進程中,像這樣:

 // (100+ items to iterate over) 

    items.forEach(function(exec){ 

     const n = cp.spawn('node', [exec], { 
      stdio: ['ignore','pipe','pipe','ipc'] 
     }); 

     n.stdout.setEncoding('utf8'); 
     n.stderr.setEncoding('utf8'); 

     n.stdout.on('data', function(d){ 
      // do something with the data 
     }); 

     n.stderr.on('data', function(d){ 
      // do something with the data 
     }); 

    }); 

我假設

  1. 我認爲,如果我們用「忽略」的標準輸出和在父進程中stderr, 這比管道標準輸出/標準錯誤到父進程更高性能。
  2. 我認爲,如果我們選擇一個文件流的標準輸出/標準錯誤喜歡這樣

    stdio: ['ignore', fs.openSync('/some/file.log'), fs.openSync('/some/file.log'),'ipc']

,這幾乎是用「忽略」的標準輸出/標準錯誤(應該送作爲高性能stdout/stderr到/ dev/null)

這些假設是否正確?關於stdout/stderr,如果我想將stdout/stderr記錄到某處(而不是/ dev/null),如何實現最高性能?

注:這是一個庫,所以stdout/stderr的數量可能會有很大的不同。此外,最有可能很少分叉更多的進程比核心,最多同時運行約15個進程。

+0

如果源代碼出現問題,部分答案在這裏:https://github.com/nodejs/node/blob/master/lib/child_process.js –

+0

並在這裏:https://github.com/ nodejs/node/blob/master/lib/internal/child_process.js –

+0

你的程序庫需要分叉多少子進程? – robertklep

回答

1

這些假設是否正確?

我該如何實現最高性能?

測試它。這就是你如何實現最高性能。測試您將在生產中使用的相同類型的系統,具有相同數量的CPU和類似的磁盤(SSD或HDD)。

我假設你的擔心是,如果父母讀得不夠快,孩子可能會被阻止。這是一個潛在的問題,取決於管道的緩衝區大小以及流經它的數據量。但是,如果替代方法是讓每個子進程獨立寫入磁盤,則可能會更好,相同或更糟。我們並不知道一大堆原因,首先是我們不知道您有多少內核,您的進程生成數據的速度以及您寫入的I/O子系統。

如果您有一個SSD,則可以每秒寫入500 MB。這太好了,但如果SSD的容量是512 GB,那麼它只會在滿滿之前持續16分鐘!在任何人都知道什麼是最有效的方法之前,你需要縮小問題空間的範圍。

如果您的目標僅僅是儘可能少的系統利用率從機器上獲取記錄的數據,那麼最好的辦法就是直接將日誌消息寫入網絡。

+0

那麼,這將運行在各種系統上,因爲這是針對圖書館的。因此,或許我們可以在某種程度上假定除了所討論的變量之外「所有事情都是平等的」 - 這實際上是否將一個孩子的stdout/stderr傳遞給父級,而不是將它傳遞給/ dev/null或一個文件,我只是不太清楚計算機是否可以確定的方式。 –

+0

我可以在我的系統上測試它,但它不會像下一個在它們上運行它的人那樣相同,我只想知道平均情況/所有其他東西是相等/固定的情況 –

+0

@AlexanderMills你應該說你正在寫一個圖書館!這非常重要,你根本沒有提及它!告訴我們更多關於它的信息......僅供內部使用一個項目,內部使用於您工作的公司中的許多項目的內部使用,還是供您可能永遠不會互動的人員使用?如果是後者,如果不能測試哪種方式更好,則可以將其配置爲可配置。 –

1

您有以下選擇:

  • 你可以有子進程完全忽略標準輸出/標準錯誤,並以任何其他方式自行做記錄(記錄一個到一個文件,系統日誌... )

  • 如果您記錄父進程的輸出,則可以分別將stdout/stderr設置爲process.stdoutprocess.stderr。這意味着孩子的輸出將與主要過程相同。沒有任何東西會流過主流程

  • 您可以直接設置文件描述符。這意味着子進程的輸出將在給定的文件中執行,而不通過父進程

  • 但是,如果您沒有對子進程的任何控制權,並且您需要以某種方式對日誌執行某些操作(過濾它們,在關聯的子進程中加上前綴等),那麼你可能需要經過父進程。

由於我們不知道您所談論的日誌量,我們不知道這是關鍵還是過早優化。 Node.js是異步的,我不希望你的父進程成爲瓶頸,除非它真的很忙,並且你有很多日誌。

+0

我確實在一定程度上可以控制子進程 - 但是日誌記錄的容量可能會有很大差異,具體取決於用戶,並且在某些情況下,我假定可以記錄很多stdout/stderr –

+0

「很多」是多少? – jcaron

+0

我不知道,但如果你有100個進程都向單個進程發送大量的stdout/stderr,並且該進程必須處理它,我認爲它會比如果這100個進程各自獨立發送它們的標準輸出/ stderr來分離文件 –