为什么python运行的慢
最近在leetcode刷题,明显的注意到同样的算法,python运行的要慢的多,查资料得到python运行的慢主要原因如下:
一、动态类型导致运行速度慢,在北邮人论坛里面的这篇帖子中有较为详细的解释,原文中有举例说明,本文没有例子讲解只是提取了原理来讲解,内容主要如下:
(原文链接:http://bbs.byr.cn/#!article/Python/68)
a、动态语言中的执行过程
Python等动态类型语言之所以慢,就是因为每一个简单的操作都需要大量的指令才能完成。他们的虚拟机拥有很强的优化器,却是为静态语言设计的。对Python几乎没有效果。举一个例子。对于整数加法,C语言很简单,只要一个机器指令ADD就可以了,最多不过再加一些内存读写。但是,对于Python来说,a+b这样的简单二元运算,可就真的很麻烦了。Python是动态语言,变量只是对象的引用,变量a和b本身都没有类型,而它们的值有类型。所以,在相“加”之前,必须先判断类型。
1. 判断a是否为整数,否则跳到第9步
2. 判断b是否为整数,否则跳到第9步
3. 将a指向的对象中的整数值读出来
4. 将b指向的对象中的整数值读出来
5. 进行整数相加
6. 生成一个新整数对象
7. 将运算结果存进去
8. 返回这个对象,完成!
9. 判断a是否为字符串,否则跳到第13步
10. 判断b是否为字符串,否则跳到第13步
11. 进行字符串串接操作,生成一个新字符串对象
12. 返回这个对象,完成!
13. 从a的字典里取出__add__方法
14. 调用这个方法,将a和b作为参数传入
15. 返回上述方法的返回值。
这还只是简化版的,实际中还要考虑溢出问题等。
b、Jpython
Jython能做的只是把Python代码转换成JVM的代码,而Python中那些判断a,b是否为整数或者字符串的操作是不能省略的。毕竟Python是允许你写1+2同时也可以"hello"+"world"。这种运行时的类型检查并不能简单地通过编译而去除。
c、谷歌的Unladen Swallow项目
它是一个很有雄心的项目,但是,在项目开始一年后就流产了。最后,加速效果也不过50%左右。它们使用的方法是朴素的“模板编译法”:看到Python的加法操作,就转换成一个C语言的函数调用,调用Python的PyNumber_Add函数。这个函数就是干类似上面一串的事。同样地,虽然去除了官方Python的解释器代价,但并没有消除运行时类型检查的代价。
d、pypy为什么比较快和pypy的不足:
PyPy可以将Python的速度加到C的一半左右。PyPy使用了一种技巧,就是“类型推导”(Type Inference)。PyPy的运行时编译器(Just-in-time compiler,或者称JIT Compiler)的工作方式是,只优化循环,因为大量的时间都是消耗在少数循环上。当运行时检测到某个循环运行的次数很多的时候,就开启一个“录像机”,录制这个循环执行一次中,执行的所有操作的轨迹。这样以“轨迹”为单位的编译方式叫Tracing JIT。当类型确定以后,其中涉及的数据都是整数,都可以直接对应机器指令进行执行。程序起码在这一部分已经由动态的代码变成像C一样的静态类型代码了,而且数据类型很接近机器。将这一段代码编译成机器码,效率就可以和C相比了。
注意到,这其实是一种“猜测”:优化器“猜想”每次执行循环for i in range(n),i和n都是整数。这种猜测是可能出错的。万一程序员将一个字符串传入函数怎么办呢?所以,基于“猜测”(speculation)的优化必须考虑“猜错了”的情形。这就是优化过的代码的第1、3、11行的用途。1和3考虑万一i和n不是整数的情形,而15考虑了整数溢出的情况。在Python里,整数都是高精度整数,可以是任意大的,而不仅限于32位。(其实上述32位也只是假设,在64位机上,显然64位效率更高。)所以,如果猜错了(这种事经常会发生),就必须停止执行这段“优化”过的代码,而是老老实实回到解释器中,像传统的Python一样执行。
可以看出,带有类型推导功能的Tracing JIT编译器可以大幅度加快动态语言的速度。主要原因是:
1. 在运行时得到了变量的类型,并通过“猜测”,将这些类型转换成接近机器的类型。
2. 将简化的操作编译成机器码,去除了解释器的代价。
目前,PyPy是一个很活跃的项目。但是,毕竟是一个研究型的项目,PyPy也有自己的不足。如和官方Python并不完全兼容;PyPy本身的可执行文件很大;并不是运行所有的程序都快——PyPy虽然JIT Compiler很快,但它的解释器速度不如官方的Python,对于无法通过优化加速的程序来说,PyPy就不快了。
二、python慢不仅是因为动态类型,甚至不是python慢的主要原因,在现实中,在C语言和Python在运行时的巨大的不同是由于数据结构和算法的不同。
原文链接:http://ourjs.com/detail/5320393ab79767cf7b000004
用Python写不同的代码
point = {'x': 0, 'y': 0}
struct Point {
int x;
int y;
};
std::hash_set point;
point[“x”] = x
point[“y”] = y
class Point(object):
x, y = None, None
def __init__(self, x, y):
self.x, self.y = x, y
def sum_(points):
sum_x, sum_y = 0, 0
for point in points:
sum_x += point['x']
sum_y += point['y']
return sum_x, sum_y
为什么python运行的慢的更多相关文章
- Python黑帽编程1.3 Python运行时与包管理工具
Python黑帽编程1.3 Python运行时与包管理工具 0.1 本系列教程说明 本系列教程,采用的大纲母本为<Understanding Network Hacks Attack and ...
- Java和Python运行速度对比
Java和Python运行速度对比:同一个函数运行一百万次,Java耗时0.577秒,Python耗时78秒--135倍的差距. 版本:Java 8,Python 2.7.10 Java测试代码: i ...
- python 运行python manege.py runserver时报错:“no module named djangorestframework” 的解决方案
python 运行python manege.py runserver时报错:“no module named djangorestframework” 的解决方案 importerror:no mo ...
- Python运行Google App Engineer时出现的UnicodeDecodeError错误解决方案
#Python运行Google App Engineer时出现的UnicodeDecodeError错误解决方案 ##问题描述 使用Python2.7.x运行GAE时有时会报这个错误 ```py ...
- 自动化测试 Appium之Python运行环境搭建 Part2
Appium之Python运行环境搭建 Part2 by:授客 QQ:1033553122 实践环境 参见 Appium之Python运行环境搭建 Part1 环境部署 1.安装Android SDK ...
- 自动化测试 Appium之Python运行环境搭建 Part1
Appium之Python运行环境搭建 Part1 by:授客 QQ:1033553122 实践环境 Win7 Python 3.4.0 JAVA JDK 1.8.0_121 node.js8.11. ...
- day2 编程语言介绍、Python运行程序的两种方式、变量
一 编程语言介绍 1. 机器语言 用计算机能理解的二进制指令直接编写程序,直接控制硬件 2. 汇编语言 用英文标签取代二进制指令编写程序,本质也是直接控制硬件 3. 高级语言 用人能理解的表达方式去编 ...
- 用 virtualenv 创建隔离的 Python 运行环境
以 Ubuntu 14.04 系统为例,安装的 Python 和 Python3 分别是 2.7.6 和 3.4.3, 但有些项目,有些模块要求特定的 Python 版本.而当前系统默认的 Pytho ...
- 隔离python 运行环境和Pycharm 设置代码同步
隔离python 运行环境 查看当前有哪些虚拟环境:workon 进入虚拟环境:workon django 退出虚拟环境:deactivate 创建虚拟环境: mkvirtualenv -p /usr ...
随机推荐
- Nginx入门篇-基础知识与linux下安装操作
我们要深刻理解学习NG的原理与安装方法,要切合实际结合业务需求,应用场景进行灵活使用. 一.Nginx知识简述Nginx是一个高性能的HTTP服务器和反向代理服务器,也是一个 IMAP/POP3/SM ...
- POJ1821 单调队列//ST表 优化dp
http://poj.org/problem?id=1821 当我们在考虑内层循环j以及决策k的时候,我们可以把外层变量i看作定值,以此来优化dp状态转移方程. 题意 有n个工人准备铺m个连续的墙,每 ...
- python对象继承
继承允许我们在两个或者更多的类之间创建一种“是一个”的关系,这种关系把共同的细节抽象到一个超类里. 从技术上讲,每一个我们创建的类都使用了继承,所有的python类都是一个叫做object的特殊类的子 ...
- Java基础构造方法和this关键字整理
构造方法 8.1构造方法介绍 构造方法的格式: 修饰符 构造方法名(参数列表) { } l 构造方法的体现: n 构造方法没有返回值类型.也不需要写返回值.因为它是为构建对象的,对象创建完,方法就 ...
- 简单BootLoader
目录 简单BootLoader 概述 NOR与NAND启动 链接脚本规划 初始化规划 参数设置 title: 简单BootLoader tags: linux date: 2018-09-28 23: ...
- web.xml 文件头
Servlet 2.3 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN ...
- springmvc上传图片《2》
创建springboot项目 编写配置 server: port: 8082 spring: application: name: upload-service servlet: multipart: ...
- ACM-ICPC 2018 南京赛区网络预赛 B The writing on the wall(思维)
https://nanti.jisuanke.com/t/30991 题意 一个n*m的方格矩阵,有的格子被涂成了黑色,问该矩阵中有多少个子矩阵,子矩阵不包含黑色格子. 分析 参考https://bl ...
- maven构建项目时硬编码中文乱码问题解决
场景:1. 项目采用maven作为构建工具.2. 前端页面为jsp,由前端团队独立完成,添加编码配置:<%@ page contentType="text/html;charset=u ...
- Windows Server 2008 R2中无法使用360免费Wifi的解决方案
为了使主机和虚拟机在同一个无线网络中,而虚拟机的系统是Windows Server 2008 R2 64位的,使用360免费wifi,始终无法开启.在网上查找解决方案,终于找到了原因:Windows ...