![](/img/trans.png)
[英]Writing an asynchronous method in Javascript (Code run in Node.js)
[英]Does node.js run asynchronous file reading/writing in main thread?
我原以為讀取文件等異步處理在其他線程上處理,在其他線程讀完時通知主線程。
我試過跟隨。
const fs = require("fs")
console.time(1)
fs.readFile("largefile", x => console.timeEnd(1))
這顯示1500ms
。
其次我試着跟隨。
const fs = require("fs")
console.time(1)
fs.readFile("largefile", x => console.timeEnd(1))
// block main thread 1sec
const s = Date.now()
while(Date.now() - s < 1000);
如果在其他線程上處理異步進程,它將顯示1500ms
。 但是,我得到了2500ms
。
我嘗試了另一個。
const fs = require("fs")
console.time(1)
fs.readFile("largefile", x => console.timeEnd(1))
setInterval(() => {
const s = Date.now()
while(Date.now() - s < 100);
}, 100)
我等了幾分鍾,但沒有消息。
nodejs是否在主線程上處理繁重的處理?
當我需要讀取和寫入太多大文件時,我應該使用child_process
嗎?
I / O是在封面下使用非阻塞操作完成的(而不是占用主線程); 但是,I / O 完成 (例如,回調)是在啟動I / O操作的線程上完成的(在您的示例中,一個主要的JavaScript線程,因為您沒有使用worker )。 如果你使該線程飽和,它就沒有機會處理回調。
你的例子中的主要問題是
您正在使用便捷函數readFile
將大文件一次性讀入內存。
您的測試是合成的,執行極其耗費CPU的事情,不太可能模擬您的實際應用程序的特征。
nodejs是否在主線程上處理繁重的處理?
諸如readFile
之類的便利函數的某些部分是在你調用它的線程(你的例子中的主線程)上實現的,是的。 readFile
是使用fs.read
在JavaScript中fs.read
,並且在處理完前一個塊之后才會請求下一個數據塊。 塊的默認大小(截至本文時)為8k(8,192)字節。
你可以在源代碼中看到這個:
lib/fs.js
,它使用ReadFileContext
對象顯示readFile
。 internal/fs/read_file_context.js
,它顯示了ReadFileContext
對象的實現,我們可以看到它通過fs.read
以塊的fs.read
讀取。 這意味着如果主線程被阻塞(你的第二個代碼塊)或負載極重(你的第三個代碼塊),那么處理每8k一次的read
回調非常慢,這會極大地影響便利功能的性能:
setInterval
調用忙等待100ms每100ms)與readFile
的實現合謀,在從文件讀取的每個8k塊之間引入~100ms的延遲。 任何大小的文件都需要很長時間才能以~820字節/秒的速度讀取。 但是,你的測試再次是合成的。 即使是一次100毫秒阻塞主線程也是不尋常的。
當我需要讀取和寫入太多大文件時,我應該使用child_process嗎?
不能。只需使用基本I / O操作( read
, write
或流 )以合理大小的塊進行,而不是使用readFile
等便捷功能。 使用子進程對於使用工作線程至少同樣糟糕,甚至更糟,Node.js開發團隊在工作線程文檔中有這樣的說法:
worker對於執行CPU密集型JavaScript操作很有用; 不要將它們用於I / O,因為Node.js用於異步執行操作的內置機制已經比工作線程更有效地處理它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.