欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Node.js 多進(jìn)程處理CPU密集任務(wù)的實(shí)現(xiàn)

 更新時(shí)間:2019年05月26日 14:12:26   作者:Svend  
這篇文章主要介紹了Node.js 多進(jìn)程處理CPU密集任務(wù)的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

Node.js 單線程與多進(jìn)程

大家都知道 Node.js 性能很高,是以異步事件驅(qū)動(dòng)、非阻塞 I/O 而被廣泛使用。但缺點(diǎn)也很明顯,由于 Node.js 是單線程程序,如果長(zhǎng)時(shí)間運(yùn)算,會(huì)導(dǎo)致 CPU 不能及時(shí)釋放,所以并不適合 CPU 密集型應(yīng)用。

當(dāng)然,也不是沒有辦法解決這個(gè)問題。雖然 Node.js 不支持多線程,但是可創(chuàng)建多子進(jìn)程來執(zhí)行任務(wù)。
Node.js 提供了 child_process 和 cluster 兩個(gè)模塊可用于創(chuàng)建多子進(jìn)程

下面我們就分別使用單線程和多進(jìn)程來模擬查找大量斐波那契數(shù)進(jìn)行 CPU 密集測(cè)試

以下代碼是查找 500 次位置為 35 的斐波那契數(shù)(方便測(cè)試,定了一個(gè)時(shí)間不需要太長(zhǎng)也不會(huì)太短的位置)

單線程處理

代碼:single.js

function fibonacci(n) {
 if (n == 0 || n == 1) {
  return n;
 } else {
  return fibonacci(n - 1) + fibonacci(n - 2);
 }
}

let startTime = Date.now();
let totalCount = 500;
let completedCount = 0;
let n = 35;

for (let i = 0; i < totalCount; i++) {
 fibonacci(n);
 completedCount++;
 console.log(`process: ${completedCount}/${totalCount}`);
}
console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");
console.info(`任務(wù)完成,用時(shí): ${Date.now() - startTime}ms`);
console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");

執(zhí)行node single.js 查看結(jié)果

在我的電腦上顯示結(jié)果為44611ms(電腦配置不同也會(huì)有差異)。

...
process: 500/500
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
任務(wù)完成,用時(shí): 44611ms
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏

查找 500 次需要 44 秒,太慢了。可想而知如果位置更大,數(shù)量更多...

那我們來嘗試用多進(jìn)程試試 ⬇️

多進(jìn)程

采用 cluster 模塊,Master-Worker 模式來測(cè)試

共 3 個(gè) js,分別為主線程代碼:master.js、子進(jìn)程代碼:worker.js、入口代碼:cluster.js(入口可無需單獨(dú)寫一個(gè) js、這里是為了看起來更清楚一些)

主線程代碼:master.js

const cluster = require("cluster");
const numCPUs = require("os").cpus().length;

// 設(shè)置子進(jìn)程執(zhí)行程序
cluster.setupMaster({
 exec: "./worker.js",
 slient: true
});

function run() {
 // 記錄開始時(shí)間
 const startTime = Date.now();
 // 總數(shù)
 const totalCount = 500;
 // 當(dāng)前已處理任務(wù)數(shù)
 let completedCount = 0;
 // 任務(wù)生成器
 const fbGenerator = FbGenerator(totalCount);

 if (cluster.isMaster) {
  cluster.on("fork", function(worker) {
   console.log(`[master] : fork worker ${worker.id}`);
  });
  cluster.on("exit", function(worker, code, signal) {
   console.log(`[master] : worker ${worker.id} died`);
  });

  for (let i = 0; i < numCPUs; i++) {
   const worker = cluster.fork();

   // 接收子進(jìn)程數(shù)據(jù)
   worker.on("message", function(msg) {
    // 完成一個(gè),記錄并打印進(jìn)度
    completedCount++;
    console.log(`process: ${completedCount}/${totalCount}`);

    nextTask(this);
   });

   nextTask(worker);
  }
 } else {
  process.on("message", function(msg) {
   console.log(msg);
  });
 }

 /**
  * 繼續(xù)下一個(gè)任務(wù)
  *
  * @param {ChildProcess} worker 子進(jìn)程對(duì)象,將在此進(jìn)程上執(zhí)行本次任務(wù)
  */
 function nextTask(worker) {
  // 獲取下一個(gè)參數(shù)
  const data = fbGenerator.next();
  // 判斷是否已經(jīng)完成,如果完成則調(diào)用完成函數(shù),結(jié)束程序
  if (data.done) {
   done();
   return;
  }
  // 否則繼續(xù)任務(wù)
  // 向子進(jìn)程發(fā)送數(shù)據(jù)
  worker.send(data.value);
 }

 /**
  * 完成,當(dāng)所有任務(wù)完成時(shí)調(diào)用該函數(shù)以結(jié)束程序
  */
 function done() {
  if (completedCount >= totalCount) {
   cluster.disconnect();
   console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");
   console.info(`任務(wù)完成,用時(shí): ${Date.now() - startTime}ms`);
   console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");
  }
 }
}

/**
 * 生成器
 */
function* FbGenerator(count) {
 var n = 35;
 for (var i = 0; i < count; i++) {
  yield n;
 }
 return;
}

module.exports = {
 run
};

1.這里是根據(jù)當(dāng)前電腦的邏輯 CPU 核數(shù)來創(chuàng)建子進(jìn)程的,不同電腦數(shù)量也會(huì)不一樣,我的 CPU 是 6 個(gè)物理核數(shù),由于支持超線程處理,所以邏輯核數(shù)是 12,故會(huì)創(chuàng)建出 12 個(gè)子進(jìn)程

2.主線程與子進(jìn)程之間通信是通過send方法來發(fā)送數(shù)據(jù),監(jiān)聽message事件來接收數(shù)據(jù)

3.不知道大家有沒有注意到我這里使用了 ES6 的 Generator 生成器來模擬生成每次需要查找的斐波那契數(shù)位置(雖然是寫死的 😂,為了和上面的單線程保證統(tǒng)一)。這么做是為了不讓所有任務(wù)一次性扔出去,因?yàn)榫退闳映鋈ヒ矔?huì)被阻塞,還不如放在程序端就給控制住,完成一個(gè),放一個(gè)。

子進(jìn)程代碼:worker.js

function fibonacci(n) {
 if (n == 0 || n == 1) {
  return n;
 } else {
  return fibonacci(n - 1) + fibonacci(n - 2);
 }
}

// 接收主線程發(fā)送過來的任務(wù),并開始查找斐波那契數(shù)
process.on("message", n => {
 var res = fibonacci(n);
 // 查找結(jié)束后通知主線程,以便主線程再度進(jìn)行任務(wù)分配
 process.send(res);
});
入口代碼:cluster.js
// 引入主線程js,并執(zhí)行暴露出來的run方法
const master = require("./master");
master.run();

執(zhí)行node cluster.js 查看結(jié)果

在我的電腦上顯示結(jié)果為10724ms(電腦配置不同也會(huì)有差異)。

process: 500/500
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
任務(wù)完成,用時(shí): 10724ms
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏

結(jié)果

進(jìn)過上面兩種方式的對(duì)比,結(jié)果很明顯,多進(jìn)程處理速度是單線程處理速度的 4 倍多。而且有條件的情況下,如果電腦 CPU 足夠,進(jìn)程數(shù)更多,那么速度也會(huì)更快。

如果有更好的方案或別的語言能處理你的需求那就更好,誰讓 Node.js 天生就不適合 CPU 密集型應(yīng)用呢。。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • nodejs個(gè)人博客開發(fā)第五步 分配數(shù)據(jù)

    nodejs個(gè)人博客開發(fā)第五步 分配數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了nodejs個(gè)人博客開發(fā)的分配數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • koa2使用ejs和nunjucks作為模板引擎的使用

    koa2使用ejs和nunjucks作為模板引擎的使用

    這篇文章主要介紹了koa2使用ejs和nunjucks作為模板引擎的使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-11-11
  • node.js 用socket實(shí)現(xiàn)聊天的示例代碼

    node.js 用socket實(shí)現(xiàn)聊天的示例代碼

    本篇文章主要介紹了node.js 用socket實(shí)現(xiàn)聊天的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • nodejs實(shí)現(xiàn)獲取某寶商品分類

    nodejs實(shí)現(xiàn)獲取某寶商品分類

    這篇文章主要介紹了nodejs實(shí)現(xiàn)獲取某寶商品分類,十分的簡(jiǎn)單實(shí)用,進(jìn)入后臺(tái)直接打開控制臺(tái),把代碼粘進(jìn)去運(yùn)行就OK了,有需要的小伙伴可以參考下。
    2015-05-05
  • 基于nodejs res.end和res.send的區(qū)別

    基于nodejs res.end和res.send的區(qū)別

    今天小編就為大家分享一篇基于nodejs res.end和res.send的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • 利用nodejs監(jiān)控文件變化并使用sftp上傳到服務(wù)器

    利用nodejs監(jiān)控文件變化并使用sftp上傳到服務(wù)器

    這篇文章主要介紹了利用nodejs監(jiān)控文件變化并使用sftp上傳到服務(wù)器的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-02-02
  • 使用nodejs分離html文件里的js和css詳解

    使用nodejs分離html文件里的js和css詳解

    在本篇文章里小編給大家分享了關(guān)于如何使用nodejs分離html文件里的js和css的相關(guān)知識(shí)點(diǎn),需要的朋友參考下。
    2019-04-04
  • Node.js連接數(shù)據(jù)庫實(shí)現(xiàn)過程詳解

    Node.js連接數(shù)據(jù)庫實(shí)現(xiàn)過程詳解

    這篇文章主要為大家介紹了Node.js連接數(shù)據(jù)庫實(shí)現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • node.js require() 源碼解讀

    node.js require() 源碼解讀

    學(xué)習(xí) Node.js ,必學(xué)如何使用 require 語句。本文通過源碼分析,詳細(xì)介紹 require 語句的內(nèi)部運(yùn)行機(jī)制,幫你理解 Node.js 的模塊機(jī)制
    2015-12-12
  • 用node開發(fā)并發(fā)布一個(gè)cli工具的方法步驟

    用node開發(fā)并發(fā)布一個(gè)cli工具的方法步驟

    這篇文章主要介紹了用node開發(fā)并發(fā)布一個(gè)cli工具的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-01-01

最新評(píng)論