本文经过分析对比探究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… 做者信息:朱德龙,人和将来高级前端工程师。