成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

壓榨計算機性能:瀏覽器和 Node.js 的異步計算

系統 瀏覽器
所有的軟件代碼最終都是通過 CPU 來跑的,能不能把 CPU 高效利用起來是區分性能高低的標志,也就是說不能讓它空轉。

[[421495]]

本文轉載自微信公眾號「神光的編程秘籍」,作者神說要有光。轉載本文請聯系神光的編程秘籍公眾號。

都說 Node.js 可以實現高性能的服務器,那什么是高性能呢?

所有的軟件代碼最終都是通過 CPU 來跑的,能不能把 CPU 高效利用起來是區分性能高低的標志,也就是說不能讓它空轉。

那什么時候會空轉呢?

  • 當程序在進行網絡和磁盤的 IO 的時候,這時候 CPU 是空閑的,也就是在空轉。
  • 多核 CPU 可以同時跑多個程序,如果只利用了其中一核,那么其他核也是在空轉。

所以,要想達到高性能,就要解決這兩個問題。

操作系統提供了線程的抽象,對應代碼不同的執行分支,都是可以同時上不同的 CPU 跑的,這是利用好多核 CPU 性能的方式。

而如果有的線程在進行 IO 了,也就是要阻塞的等待讀寫完成,這種是比較低效的方式,所以操作系統實現了 DMA 的機制,就是設備控制器,由硬件來負責從設備到內存的搬運,在搬完了告訴 CPU 一聲。這樣當有的線程在 IO 的時候就可以把線程暫停掉,等收到 DMA 運輸數據完成的通知再繼續跑。

多線程、DMA,這是利用好多核 CPU 優勢、解決 CPU 阻塞等 IO 的問題的操作系統提供的解決方案。

而各種編程語言對這種機制做了封裝,Node.js 也是,Node.js 之所以是高性能,就是因為異步 IO 的設計。

Node.js 的異步 IO 的實現在 libuv,基于操作系統提供的異步的系統調用,這種一般是硬件級別的異步,比如 DMA 搬運數據。但是其中有一些同步的系統調用,通過 libuv 封裝以后也會變成異步的,這是因為 libuv 內有個線程池,來執行這些任務,把同步的 API 變成異步的。這個線程池的大小可以通過 UV_THREADPOOL_SIZE 的環境變量設置,默認是 4。

我們在代碼里調用的異步 API,很多都是通過線程來實現的。

比如:

  1. const fsPromises = require('fs').promises; 
  2.  
  3. const data = await fsPromises.readFile('./filename'); 

但是,這種異步 API 只解決了 IO 的問題,那如何利用多核 CPU 的優勢來做計算呢?

Node.js 在 10.5 實驗性的引入(在 12 正式引入)了 worker_thread 模塊,可以創建線程,最終用多個 CPU 跑,這是利用多核 CPU 的做計算的方式。

異步 API 可以利用多線程做 IO,而 worker_thread 可以創建線程做計算,用于不同的目的。

要聊清楚 worker_thread,還得從瀏覽器的 web worker 聊起。

瀏覽器的 web worker

瀏覽器也同樣面臨不能利用多核 CPU 做計算的問題,所以 html5 引入了 web worker,可以通過另一個線程做計算。

我們創建一個 Worker 對象,指定跑在另一個線程的 js 代碼,然后通過 postMessage 傳遞消息給它,通過 onMessage 接收消息。這個過程也是異步的,我們進一步把它封裝成了 promise。

然后在 webWorker.js 里面接收數據,做計算,之后通過 postMessage 傳回結果。

  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head></head> 
  4. <body> 
  5.     <script> 
  6.         (async function () { 
  7.             const res = await runCalcWorker(2, 3, 3, 3); 
  8.             console.log(res); 
  9.         })(); 
  10.  
  11.         function runCalcWorker(...nums) { 
  12.             return new Promise((resolve, reject) => { 
  13.                 const calcWorker = new Worker('./webWorker.js'); 
  14.                 calcWorker.postMessage(nums) 
  15.                 calcWorker.onmessage = function (msg) { 
  16.                     resolve(msg.data); 
  17.                 }; 
  18.                 calcWorker.onerror = reject; 
  19.             }); 
  20.         } 
  21.     </script> 
  22.  
  23. </body> 
  24. </html> 

這樣,我們就利用了另一個 CPU 核來跑了這段計算,對寫代碼來說和普通的異步代碼沒啥區別。但這個異步實際上不是 IO 的異步,而是計算的異步。

Node.js 的 worker thread 和 web worker 類似,我甚至懷疑 worker thread 的名字就是受 web worker 影響的。

Node.js 的 worker thread

把上面那段異步計算的邏輯在 Node.js 里面實現話,是這樣的:

  1. const runCalcWorker = require('./runCalcWorker'); 
  2.  
  3. (async function () { 
  4.     const res = await runCalcWorker(2, 3, 3, 3); 
  5.     console.log(res); 
  6. })(); 

以異步的方式調用,因為異步計算和異步 IO 在使用方式上沒啥區別。

  1. // runCalcWorker.js 
  2. const  { Worker } = require('worker_threads'); 
  3.  
  4. module.exports = function(...nums) { 
  5.     return new Promise(function(resolve, reject) { 
  6.         const calcWorker = new Worker('./nodeWorker.js'); 
  7.         calcWorker.postMessage(nums); 
  8.  
  9.         calcWorker.on('message', resolve); 
  10.         calcWorker.on('error', reject); 
  11.     }); 

然后異步計算的實現是通過創建 Worker 對象,指定在另一個線程跑的 JS,然后通過 postMessage 傳遞消息,通過 message 接收消息。這個和 web worker 很類似。

  1. // nodeWorker.js 
  2. const { 
  3.     parentPort 
  4. } = require('worker_threads'); 
  5.  
  6. parentPort.on('message', (data) => { 
  7.     const res = data.reduce((total, cur) => { 
  8.         return total += cur; 
  9.     }, 0); 
  10.     parentPort.postMessage(res); 
  11. }); 

在具體執行計算的 nodeWorker.js 里面,監聽 message 消息,然后進行計算,通過 parentPost.postMessage 傳回數據。

對比下 web worker,你會發現特別的像。所以,我覺得 Node.js 的 worker thread 的 api 是參考 web worker 來設計的。

但是,其實 worker thread 也支持在創建的時候就通過 wokerData 傳遞數據:

  1. const  { Worker } = require('worker_threads'); 
  2.  
  3. module.exports = function(...nums) { 
  4.     return new Promise(function(resolve, reject) { 
  5.         const calcWorker = new Worker('./nodeWorker.js', { 
  6.             workerData: nums 
  7.         }); 
  8.         calcWorker.on('message', resolve); 
  9.         calcWorker.on('error', reject); 
  10.     }); 

然后 worker 線程里通過 workerData 來取:

  1. const { 
  2.     parentPort, 
  3.     workerData 
  4. } = require('worker_threads'); 
  5.  
  6. const data = workerData; 
  7. const res = data.reduce((total, cur) => { 
  8.     return total += cur; 
  9. }, 0); 
  10. parentPort.postMessage(res); 

因為有個傳遞消息的機制,所以要做序列化和反序列化,像函數這種無法被序列化的數據就無法傳輸了。這也是 worker thread 的特點。

Node.js 的 worker thread 和 瀏覽器 web woker 的對比

從使用上來看,都可以封裝成普通的異步調用,和其他異步 API 用起來沒啥區別。

都要經過數據的序列化反序列化,都支持 postMessage、onMessage 來收發消息。

除了 message,Node.js 的 worker thread 支持傳遞數據的方式更多,比如還有 workerData。

但從本質上來看,兩者都是為了實現異步計算,充分利用多核 CPU 的性能,沒啥區別。

總結

高性能的程序也就是要充分利用 CPU 資源,不要讓它空轉,也就是 IO 的時候不要讓 CPU 等,多核 CPU 也要能同時利用起來做計算。操作系統提供了線程、DMA的機制來解決這種問題。Node.js 也做了相應的封裝,也就是 libuv 實現的異步 IO 的 API,但是計算的異步是 Node 12 才正式引入的,也就是 worker thread,API 設計參考了瀏覽器的 web worker,傳遞消息通過 postMessage、onMessage,需要做數據的序列化,所以函數是沒法傳遞的。 

從使用上來看異步計算、異步 IO 使用方式一樣,但是異步 IO 只是讓 cpu 不同阻塞的等待 IO 完成,異步計算是利用了多核 CPU 同時進行并行的計算。

 

責任編輯:武曉燕 來源: 神光的編程秘籍
相關推薦

2022-08-21 07:30:55

程序并發Golang編碼

2022-01-04 21:36:33

JS瀏覽器設計

2021-12-08 07:55:41

EventLoop瀏覽器事件

2012-03-09 09:11:29

Node.js

2021-03-04 23:12:57

Node.js異步迭代器開發

2020-09-15 08:26:25

瀏覽器緩存

2021-04-06 10:15:29

Node.jsHooks前端

2009-04-01 08:56:59

2021-03-16 16:16:41

GeneratorWebsockets前端

2011-12-23 13:58:57

node.js

2025-01-13 00:00:00

2019-07-09 14:50:15

Node.js前端工具

2020-12-08 06:28:47

Node.js異步迭代器

2021-09-07 07:53:43

工具

2021-08-12 15:00:01

Linux終端

2018-02-27 14:20:18

Python異步并發連接

2021-01-26 08:07:44

Node.js模塊 Async

2013-11-01 09:34:56

Node.js技術

2019-09-19 09:30:53

量子計算機芯片超算

2015-03-10 10:59:18

Node.js開發指南基礎介紹
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美精品免费观看二区 | 久久av一区二区三区 | 男人的天堂亚洲 | 久久久精 | 国产精品久久久久久网站 | 欧美日韩不卡 | 亚洲国产精品一区二区www | 黄色网址免费在线观看 | 欧美国产91 | 国产一级在线观看 | av手机免费在线观看 | 91亚洲欧美 | 午夜在线观看视频 | 欧美日韩精品免费 | 国产露脸对白88av | 久久精品亚洲 | 国产成人精品一区 | 亚洲黄色视屏 | 欧美一级片中文字幕 | 97色综合 | 亚洲激情综合 | 欧美国产日韩一区二区三区 | 色吧色综合| 暖暖日本在线视频 | 99精品在线观看 | 国产黄色精品 | 国产女人与拘做受视频 | 国产一级影片 | 国产一区二区在线免费观看 | 国产精品色哟哟网站 | 成人午夜精品一区二区三区 | 成人午夜激情 | 美女在线一区二区 | 色婷婷国产精品综合在线观看 | 国产日韩欧美电影 | 亚洲一区二区久久 | 久久久久久久久久久久91 | 色婷婷综合久久久中字幕精品久久 | av片网站| 中文字幕在线人 | 欧美一区中文字幕 |