本文經過分析對比探究JavaScript與Python的併發能力,分上下兩篇,上篇探究CPU併發,下篇探究網絡IO併發。html
測試環境:前端
操做系統: win10 x64
CPU: Intel i5-8400 6核6線程
複製代碼
用一個簡單的耗時功能來進行測試:遞歸實現斐波那契數列第n項的計算。github
對於CPU密集型的計算任務,要經過併發提高程序執行效率,縮短執行時間,就必定要利用CPU的多核。 下面咱們就來看看 JavaScript 和 Python 如何使用這3種方式進行併發以及對CPU核數的利用狀況。web
進程是系統進行資源分配和調度的基本單位。瀏覽器
瀏覽器端執行的JavaScript
沒有多進程的概念,因此只考慮Node.js
上的多進程。bash
讓不一樣的進程運行在不一樣的內核上才能最好地發揮並行的優點,爲了達到這個目的,咱們選取原生模塊cluster
。服務器
代碼以下:網絡
爲了使結果更準確,打開資源監視器進行查看,CPU各個都已跑滿。前端工程師
執行結果:
消耗時間(s): 8.107
消耗時間(s): 8.118
消耗時間(s): 8.16
消耗時間(s): 8.175
消耗時間(s): 8.209
消耗時間(s): 8.253
複製代碼
因此總耗時在8.253秒。
爲了進一步證明,執行單進程代碼:
單進程執行結果: 消耗時間(s): 7.361
時間比多進程略少一些,考慮到進程的建立與銷燬所耗的時間,在偏差範圍以內。
Python
操做進程的模塊爲multiprocessing
,一樣咱們啓動6個進程看看能不能把全部核跑滿。
代碼以下:
CPU監控也顯示6個核都執行了計算任務:
執行結果
消耗時間(s): 8.683971881866455
消耗時間(s): 8.699971675872803
消耗時間(s): 8.71097183227539
消耗時間(s): 8.84197187423706
消耗時間(s): 8.863972425460815
消耗時間(s): 8.900972843170166
複製代碼
總執行時間約爲8.9秒。
執行時間看上去只比JavaScript
慢了那麼一丟丟,可是須要注意的是JavaScript
代碼計算的是數列第45位,Python
只計算第38位!
一樣執行一下單進程進行計算,與多進程進行對比驗證。
消耗時間(s): 8.092010259628296
執行時間也至關接近。
JavaScript(Node.js)
和Python
都提供了操做進程的原生模塊,多進程執行計算任務時都能有效利用CPU多核提高效率。
一個進程能夠有一個或多個線程,線程相對進程而言更輕量,上下文切換成本更低,一般做爲併發操做的首選。
前端工程師不多瞭解線程的概念:瀏覽器端直到HTML5標準提出才支持以web worker
方式建立多線程,Node.js也是12之後的版本才支持使用worker_threads
模塊進行多線程計算。 總結起來就是早期的JavaScript
執行環境沒有線程相關模塊與API,對開發者屏蔽了線程的概念。
瀏覽器端多線程執行執行JavaScript
代碼分爲兩部分,待執行的js
文件和引入該js
文件的頁面。
代碼以下:
在本地啓動和訪問服務器,獲得監控圖像也是多核執行:
執行結果:
消耗時間(s): 15.989
消耗時間(s): 16.109
消耗時間(s): 16.204
消耗時間(s): 16.874
消耗時間(s): 16.876
消耗時間(s): 16.971
複製代碼
總執行時間約爲16.9秒。
爲了使結果更有說服力,咱們在瀏覽器控制檯執行一下相關代碼
時間略少於多線程執行。
相對於Node.js端執行多了1倍,看來瀏覽器端的線程性能並不高。
不能利用多核一直讓Node.js
飽受詬病,新版本算是對這個問題打了個補丁。
Node.js
端代碼以下:
CPU監控結果:
執行結果:
消耗時間(s): 8.229
消耗時間(s): 8.282
消耗時間(s): 8.299
消耗時間(s): 8.403
消耗時間(s): 8.417
消耗時間(s): 8.44
複製代碼
總時間8.44秒與單獨執行至關。
瀏覽器和Node.js
都支持多線程,但明顯瀏覽器執行性能不如Node.js
,因此使用web worker
的工程師需謹慎。
Python
的原生模塊threading
提供多線程操做。具體代碼以下
看波形圖應該是利用了各個核,但並無滿負荷運行。
執行結果也不盡如人意:
消耗時間(s): 38.476489543914795
消耗時間(s): 41.6956250667572
消耗時間(s): 45.613648414611816
消耗時間(s): 47.564653396606445
消耗時間(s): 47.68662452697754
消耗時間(s): 48.57262468338013
複製代碼
總時間爲48.5s,是單進程執行時間的6倍。
從輸出結果時間來看,Python
的線程是併發執行了,但並無提高執行效率。
協程和線程有些相似,區別在於線程是由操做系統調度的,協程是由用戶代碼管理的。 相對線程而言上下文切換成本更輕量。
抱歉,JavaScript
的原生模塊目前還不支持。 Python3
卻是積極引入了協程的概念,實際做用看測試結果吧~
代碼:
CPU監控:
執行結果:
消耗時間(s): 8.070001602172852
消耗時間(s): 16.14399790763855
消耗時間(s): 24.214999198913574
消耗時間(s): 32.300398111343384
消耗時間(s): 40.38105368614197
消耗時間(s): 48.451064109802246
複製代碼
協程在CPU使用率上和線程差很少,並無提高。並且從輸出結果來看並非真正的並行執行。
JavaScript
的執行效率要優於Python
。JavaScript
更勝一籌,Python
在受限於全局解釋器鎖的狀況下,多線程能夠實現併發但不能提高效率。JavaScript
完敗,但Python
的協程也不擅長處理CPU密集型操做。原文連接:tech.gtxlab.com/js2py-async… 做者信息:朱德龍,人和將來高級前端工程師。