详细内容

Python慢,这几种是常见的原因:“因为它是GIL(全局解释器锁)”,“因为它是解释语言不是编译语言”,“因为它是动态类型语言”。

推荐课程:Java教程。

究竟哪个原因对性能的影响最大?

“因为它是GIL”

现代计算机的 CPU 有多个核心,有时甚至有多个处理器。为了利用所有计算能力,操作系统定义了一个底层结构,叫做线程,而一个进程(例如 Chrome浏览器)能够生成多个线程,通过线程来执行系统指令。这样如果一个进程是要使用很多 CPU,那么计算负载就会由多个核心分担,最终使得绝大多数应用能更快地完成任务。

在撰写本文时,我的 Chrome 浏览器开了 44 个线程。另外,基于 POSIX 的操作系统(如 Mac OS 和 Linux)的线程结构和 API 与 Windows 操作系统是不一样的。操作系统还负责线程的调度。

如果你没写过多线程程序,那么你应该了解一下锁的概念。与单线程进程不同,在多线程编程中,你要确保改变内存中的变量时,多个线程不会试图同时修改或访问同一个内存地址。

CPython 在创建变量时会分配内存,然后用一个计数器计算对该变量的引用的次数。这个概念叫做“引用计数”。如果引用的数目为 0,那就可以将这个变量从系统中释放掉。这样,创建“临时”变量(如在 for 循环的上下文环境中)不会耗光应用程序的内存。

随之而来的问题就是,如果变量在多个线程中共享,CPython 需要对引用计数器加锁。有一个“全局解释器锁”会谨慎地控制线程的执行。不管有多少个线程,解释器一次只能执行一个操作。

这对 Python 应用的性能有什么影响?

如果应用程序是单线程、单解释器的,那么这不会对速度有任何影响。去掉 GIL 也不会影响代码的性能。

但如果想用一个解释器(一个 Python 进程)通过线程实现并发,而且线程是IO 密集型的(即有很多网络输入输出或磁盘输入输出),那么就会出现下面这种 GIL 竞争:

如果 Web 应用(如 Django)使用了 WSGI,那么发往 Web 应用的每个请求都会由独立的 Python 解释器执行,因此每个请求都只会有一个锁。由于 Python 解释器启动很慢,一些 WSGI 实现就支持“守护模式”,保持 Python 进程长期运行。

“因为它是解释语言”

这条理由我也听过很多,我发现它过于简化了 CPython 的实际工作原理。当你在终端上写 python myscript.py 时,CPython 会启动一长串操作,包括读取、词法分析、语法分析、编译、解释以及执行。个过程的重点就是它会在编译阶段生成.pyc文件,字节码会写到__pycache__/下的文件中(如果是Python 3),或者写到与源代码同一个目录中(Python 2)。不仅你编写的脚本是这样,所有你导入的代码都是这样,包括第三方模块。

因此绝大多数情况下(除非你写的代码只会运行一次),Python是在解释字节码并在本地执行。与Java和C#.NET比较一下:

Java将源代码编译成“中间语言”,然后Java虚拟机读取字节码并即时编译成机器码。.NET CIL也是一样的,.NET的公共语言运行时(CLR)使用即时编译将字节码编译成机器码。

那么,既然它们都使用虚拟机,以及某种字节码,为什么Python在性能测试中比Java和C#慢那么多?第一个原因是,.NET和Java是即时编译的(JIT)。

即时编译,即JIT(Just-in-time),需要一种中间语言,将代码分割成小块(或者称帧)。而提前编译(Ahead of Time,简称AOT)是编译器把源代码翻译成CPU能理解的代码之后再执行。

JIT本身并不能让执行更快,因为它执行的是同样的字节码序列。但是,JIT可以在运行时做出优化。好的GIT优化器能找到应用程序中执行最多的部分,称为“热点”。然后对那些字节码进行优化,将它们替换成效率更高的代码。

这就是说,如果你的应用程序会反复做某件事情,那么速度就会快很多。此外,别忘了Java和C#都是强类型语言,所以优化器可以对代码做更多的假设。

“因为它是动态类型语言”

“静态类型”语言要求必须在变量定义时指定其类型,例如C、C++、Java、C#和Go等。

而动态类型语言中尽管也有类型的概念,但变量的类型是动态的。a = 1

a = "foo"

在这个例子中,Python用相同的名字和str类型定义了第二个变量,同时释放了第一个a的实例占用的内存。

静态类型语言的设计目的并不是折磨人,这样设计是因为CPU就是这样工作的。如果任何操作最终都要转化成简单的二进制操作,那就需要将对象和类型都转换成低级数据结构。

Python帮你做了这一切,只不过你从来没有关心过,也不需要关心。

不需要定义类型并不是Python慢的原因。Python的设计可以让你把一切都做成动态的。你可以在运行时替换对象的方法,可以在运行时给底层系统调用打补丁。几乎一切都有可能。

而这种设计使得Python的优化变得很困难。

那么,Python的动态类型是否让Python更慢?

比较并转换类型的代价很大。每次读取、写入或引用变脸时都会检查类型

动态类型的语言很难优化。许多替代Python的语言很快的原因就是它们牺牲了便利性来交换性能。

例如Cython(http://cython.org/),它通过结合C的静态类型和Python的方式,使得代码中的类型已知,从而优化代码,能够获得84倍的性能提升

总结

Python慢的主要原因是因为它的动态和多样性。它能用于解决各种问题,但多数问题都有优化得更好和更快的解决方案。

但Python应用也有许多优化措施,如使用异步、理解性能测试工具,以及使用多解释器等。

对于启动时间不重要,而代码可能享受到JIT的好处的应用,可以考虑使用PyPy。

对于代码中性能很重要的部分,如果变量大多是静态类型,可以考虑使用Cython。

java比python快多少倍_java为什么比python快相关推荐

  1. python用多线程可以快几倍_用了python多进程,我跑程序花费的时间缩短了4倍

    应用场景:本人需要对200万条网页html格式数据进行清洗,提取文字后将分词结果写入数据库,之前做了一次,大概花费了80多个小时才跑完.机器配置是4核,内存8G:开完会领导让再改点东西重新跑一遍,然后 ...

  2. C++比Python快50倍?如何让C++和Python优势互补?(Boost::Python)

    目录 1 为什么需要多语言联合编程? 2 Python调用C++的主要方式 2.1 SWIG 2.2 Boost::Python 2.3 ctypes 3 Boost::Python安装 4 测试实例 ...

  3. bit是python最快的bitcoin库_新的Bitcoinpython节点比以前的Python库快100倍

    3月27日,Bitcoin Cash(BCH)粉丝认识了用Python编程语言编写的新BCH完整节点. 该项目名为Bitcoinpython,是一个现代化的BCH库,其创建者声称它是速度最快的Pyth ...

  4. clickhouse大数据分析技术与实战_比Hive快500倍!大数据实时分析领域的黑马

    戳蓝字"小强的进阶之路"关注我们哦! 大数据实时分析领域的黑马是ClickHouse一个用于联机分析(OLAP)的列式数据库管理系统(DBMS). clickhouse背景 俄罗斯 ...

  5. light java框架_Java框架之light-4j( 比Spring Boot快44倍,性能好 )

    Java框架之light-4j(比Spring Boot快44倍,性能好) light-java是内置了undertow服务器的REST微服务轻量Java框架,它比Spring Boot内嵌Tomca ...

  6. 比正则快M倍以上!Python替换字符串的新姿势

    来源:Python实用宝典 FlashText 算法是由 Vikash Singh 于2017年发表的大规模关键词替换算法,这个算法的时间复杂度仅由文本长度(N)决定,算法时间复杂度为O(N). 而对 ...

  7. 实战,Python处理Excel比Vba快100倍,媳妇连连夸赞今晚不用再跪搓衣板

    背景 最近经历了一次把vb脚本改造成python脚本,并获得性能提升数倍的过程,当然,这个过程也不是一帆风顺,中间也经历了一些波折,但是,也收获了一波新的认知.正好最近有时间,姑且写下来记录一下. 什 ...

  8. Python到底是什么样的语言? Python和Java比谁更快? TensorFlow的主体是用Python写的吗?

    Python到底是什么样的语言? Python和Java比谁更快? TensorFlow的主体是用Python写的吗? Python到底是什么样的语言? 解析: 这里是一些关键点:Python是解释型 ...

  9. 转载:比Python快100倍,利用spaCy和Cython实现高速NLP项目

    Cython 是一个工具包,可以使你在 Python 中编译 C 语言,这就是为什么 numpy 和 pandas 很快的原因,Cython 就是 Python 的超集.在本文中,作者将为我们介绍他的 ...

  10. 真香!spaCy+Cython比Python快100倍.....

    选自Medium      作者:Thomas Wolf 编译:机器之心(almosthuman2014) Cython 是一个工具包,可以使你在 Python 中编译 C 语言,这就是为什么 num ...

最新文章

  1. 分享个网盘,个人觉得很不错!
  2. RxJava2.x 萌新之路 操作符篇
  3. 《系统集成项目管理工程师》必背100个知识点-31WBS的分解原则
  4. 如何解决Maven依赖本地仓库eclipse报错的问题
  5. libgo 支持mysql,loadrunner通过使用libmysql.dll完成mysql的测试-Go语言中文社区
  6. 绘制不规则位图方法总结,多种实现方法,全面测试比较
  7. 刘知远老师的“灵魂发问”:关系抽取到底在乎什么?
  8. 超链接的其他用法,复合选择器
  9. 一名Android程序员的自我修养
  10. STC12C5A60S2 下载失败问题
  11. Python解决SSL不可用问题
  12. C/C++ __builtin 超实用位运算函数总结
  13. 常用的统计建模方法——差分分析
  14. SpringCloud系列【security oauth2】
  15. 流量分析平台之(流影)扩展解决方案
  16. hive的随机函数rand()
  17. GitHub快速搭建个人博客
  18. ​Kali-linux攻击路由器​
  19. OCPC系列 - OCPC介绍扫盲贴来啦
  20. System Verilog学习笔记—接口interface

热门文章

  1. 简单的扫雷游戏代码(c++)
  2. C语言函数调用之数组与指针
  3. matlab2016安装教程
  4. Mysql主从切换流程
  5. C语言练习-绘制金字塔
  6. JS表格插件(学习使用)
  7. Matlab2017b配置C++/C/Fortan编译器的问题
  8. Colmap中depth_map部分的源码
  9. RFID课程设计之图书管理系统
  10. 浅谈VMD---变分模态分解