为什么python 慢

Python越来越流行。 它用于DevOps,数据科学,Web开发和安全性。

但是,它并没有赢得任何速度奖牌。



为什么python用sql比jmeter慢 python为什么比java慢_python

Java在速度方面与C或C ++或C#或Python相比如何? 答案很大程度上取决于您正在运行的应用程序的类型。 没有基准是完美的,但是“计算机语言基准测试”是一个很好的起点

十多年来,我一直在谈论“计算机语言基准测试”。 与其他语言(例如Java,C#,Go,JavaScript,C ++)相比,Python是最慢的语言之一 。 这包括JIT (C#,Java)和AOT (C,C ++)编译器,以及诸如JavaScript之类的解释语言。

注意:当我说“ Python”时,我是在说CPython语言的参考实现。 我将在本文中引用其他运行时。

我想回答这个问题: 当Python完成比其他语言慢2到10倍的可比较应用程序时, 为什么它变慢并且我们不能使其变快

以下是最重要的理论:

  • 这是GIL(全球口译员锁)
  • 这是因为它被解释而不是被编译
  • 这是因为它是一种动态类型的语言

以下哪个原因对性能影响最大?

“这是GIL”

现代计算机配备了具有多个内核,有时还有多个处理器的CPU。 为了利用所有这些额外的处理能力,操作系统定义了一个称为线程的低级结构,在该结构中,进程(例如Chrome浏览器)可以产生多个线程,并在其中包含有关系统的指令。 这样,如果一个进程特别占用大量CPU,则可以在内核之间共享该负载,这实际上使大多数应用程序更快地完成任务。

在撰写本文时,我的Chrome浏览器有44个线程处于打开状态。 请记住,基于POSIX的线程(例如Mac OS和Linux)和Windows OS之间的线程结构和API是不同的。 操作系统还处理线程的调度。

如果您以前没有做过多线程编程,那么您需要快速熟悉锁的概念。 与单线程进程不同,您需要确保在更改内存中的变量时,多个线程不会尝试同时访问/更改相同的内存地址。

当CPython创建变量时,它会分配内存,然后计算对该变量存在多少引用,这就是称为引用计数的概念。 如果引用数为0,则它将那部分内存从系统中释放出来。 这就是为什么在for循环范围内创建“临时”变量不会消耗应用程序的内存的原因。

当多个线程共享变量时,CPython如何锁定引用计数就成为挑战。 有一个“全局解释器锁”,可以仔细控制线程的执行。 解释器一次只能执行一个操作,而不管它有多少线程。

这对Python应用程序的性能意味着什么?

如果您具有单线程,单解释器应用程序。 这不会影响速度 。 删除GIL不会影响代码的性能。

如果您想通过使用线程在单个解释器(Python进程)中实现并发,并且您的线程是IO密集型的(例如,网络IO或磁盘IO),您将看到GIL争用的后果。




为什么python用sql比jmeter慢 python为什么比java慢_java_02


摘自David Beazley的GIL可视化文章http://dabeaz.blogspot.com/2010/01/python-gil-visualized.html


如果您有一个Web应用程序(例如Django)并且使用的是WSGI,则对您的Web应用程序的每个请求都是一个单独的 Python解释器,因此每个请求只有1个锁。 由于Python解释器的启动速度很慢,因此某些WSGI实现具有“守护程序模式” ,可让您随时随地使用Python进程。

那么其他Python运行时呢?

PyPy具有GIL ,通常比CPython快3倍以上。

Jython没有GIL,因为Jython中的Python线程由Java线程表示,并受益于JVM内存管理系统。

JavaScript如何做到这一点?

好吧,首先,所有Javascript引擎都使用标记清除垃圾收集 。 如上所述,对GIL的主要需求是CPython的内存管理算法。

JavaScript没有一个GIL,但它也是一个 -threaded所以它不需要一个。 JavaScript的事件循环和Promise / Callback模式是实现异步编程而不是并发的方法。 Python在asyncio事件循环中也有类似的事情。

“因为它是一种解释语言”

我听到了很多,我发现它大大简化了CPython的实际工作方式。 如果在终端上编写了python myscript.py则CPython将开始读取,词法分析,解析,编译,解释和执行该代码的长序列。

如果您对该流程的工作方式感兴趣,那么我之前已经写过:



在6分钟内修改Python语言
这周,我向CPython核心项目提出了我的第一个请求,但请求被拒绝了:-(但不完全是…… hackernoon.com



在此过程中,重要的一点是创建一个.pyc文件,在编译器阶段,字节码序列被写入Python 3上__pycache__/或Python 2相同目录中的文件中。您的脚本,但包含您导入的所有代码,包括第三方模块。

因此,大多数时候(除非您编写只运行一次的代码?),Python会解释字节码并在本地执行。 将其与Java和C#.NET进行比较:

Java编译为“中间语言”,而Java虚拟机读取字节码,并及时将其编译为机器码。 .NET CIL相同,.NET Common-Language-Runtime(CLR)使用即时编译来处理机器代码。

那么,如果它们都使用虚拟机和某种Bytecode,为什么Python在基准测试中比Java和C#慢得多? 首先,.NET和Java是JIT编译的。

JIT或即时编译需要一种中间语言,以允许将代码拆分为块(或帧)。 提前(AOT)编译器旨在确保CPU在进行任何交互之前可以理解代码中的每一行。

JIT本身不会使执行速度更快,因为它仍在执行相同的字节码序列。 但是,JIT可以在运行时进行优化。 一个好的JIT优化器将看到应用程序的哪些部分正在执行很多,称之为“热点”。 然后,通过将其替换为更有效的版本,对这些代码位进行优化。

这意味着当您的应用程序一次又一次地执行相同的操作时,它可能会更快。 另外,请记住Java和C#是强类型语言,因此优化程序可以对代码进行更多假设。

PyPy具有JIT,并且如上一节所述,它比CPython快得多。 此性能基准测试文章会更详细地介绍-



哪个是最快的Python版本?
当然,“取决于”,但是它取决于什么,以及如何评估哪个是最快的Python版本…… hackernoon.com



那么CPython为什么不使用JIT?

JIT的缺点是:启动时间是其中之一。 CPython的启动时间已经相对较慢,PyPy的启动时间比CPython慢2-3倍。 众所周知,Java虚拟机的启动速度很慢。 .NET CLR通过从系统启动开始来解决此问题,但是CLR的开发人员还开发了运行CLR的操作系统。

如果您有一个长时间运行的Python进程,并且由于包含“热点”而可以对代码进行优化,那么JIT很有意义。

但是,CPython是通用实现。 因此,如果您正在使用Python开发命令行应用程序,那么每次调用CLI时都必须等待JIT启动会非常慢。

CPython必须尝试并提供尽可能多的用例。 有可能将JIT插入CPython,但该项目已大步停滞。

如果您想要JIT的好处并且您有适合它的工作量,请使用PyPy。

这是因为它是一种动态类型的语言

在“静态类型”语言中,必须在声明变量时指定其类型。 这些将包括C,C ++,Java,C#,Go。

在动态类型语言中,仍然存在类型的概念,但是变量的类型是动态的。



a = 1
a = "foo"



在该玩具例如,Python创建具有相同名称的第二变量和类型的str并释放对的第一个实例中创建的存储器a

静态类型的语言并不是为了让您的生活变得艰难而设计的,而是因为CPU的运行方式而设计的。 如果最终所有事情都需要等同于简单的二进制操作,则必须将对象和类型转换为低级数据结构。

Python为您做到了,您只是从未见过,也不需要关心。

不必声明类型并不是让Python变慢的原因,Python语言的设计使您几乎可以使任何东西动态化。 您可以在运行时替换对象上的方法,还可以将低级系统调用猴子补丁到运行时声明的值。 几乎所有可能。

正是这种设计使优化Python变得异常困难

为了说明我的观点,我将使用在Mac OS中工作的syscall跟踪工具Dtrace。 CPython发行版没有内置DTrace,因此您必须重新编译CPython。 我正在使用3.6.6进行演示



wget https://github.com/python/cpython/archive/v3.6.6.zip
unzip v3.6.6.zip
cd v3.6.6
./configure --with-dtrace
make



现在, python.exe在整个代码中将具有Dtrace跟踪器。 保罗·罗斯(Paul Ross)在Dtrace上写了一篇很棒的闪电演讲 。 您可以下载适用于Python的DTrace起始文件 ,以测量函数调用,执行时间,CPU时间,系统调用以及各种乐趣。 例如

sudo dtrace -s toolkit/<tracer>.d -c '../cpython/python.exe script.py'

py_callflow跟踪器显示了应用程序中的所有函数调用




为什么python用sql比jmeter慢 python为什么比java慢_java_03

那么,Python的动态类型会使其变慢吗?

  • 类型的比较和转换成本很高,每次检查,读取或引用变量时都要检查类型
  • 很难优化如此动态的语言。 Python的许多替代方法之所以如此之快,是因为它们以性能为名折衷了灵活性。
  • 看着用Cython ,它结合了C-静态类型和Python来优化代码,其中所述类型是已知的可以提供一个84X的性能改进。

结论

Python主要由于其动态特性和多功能性而速度较慢。 它可以用作解决各种问题的工具,其中可能有更优化和更快的替代方案。

但是,有多种方法可以利用异步,了解性能分析工具并考虑使用多重解释器来优化Python应用程序。

对于启动时间不重要且代码将使JIT受益的应用程序,请考虑使用PyPy。

对于代码性能至关重要且您拥有更多静态类型变量的部分代码,请考虑使用Cython

翻译自: https://hackernoon.com/why-is-python-so-slow-e5074b6fe55b

为什么python 慢