为什么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 ...
随机推荐
- php中加密和解密
项目要和第三方进行接口对接,所以数据的安全很重要.第一次自己设计并实现,学习记录下 网上查了很多资料,真的很深奥 对称加密: 双方共用一个约定好的密钥进行数据的加密和解密,但是当密匙丢失,数据将有泄露 ...
- linux服务器,发现大量TIME_WAIT
linux服务器,发现大量TIME_WAIT 今天登陆linux服务器,发现大量TIME_WAIT参考资料:http://coolnull.com/3605.html 酷喃|coolnull| » 大 ...
- i2c框架
目录 i2c框架 寄存器 主机发送 主机接收 中断处理 程序框架 title: iic框架 tags: ARM date: 2018-11-05 13:44:58 --- i2c框架 寄存器 /* 配 ...
- SQL语法基础之ALTER语句
SQL语法基础之ALTER语句 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查看ALTER的帮助信息 mysql> ? ALTER Many help items fo ...
- Spring Boot笔记一 输出hello
开始学习Spring Boot了,本篇文章你可以学到 1.Spring Boot的基本配置,输出一句hello 许嵩 2.Spring boot打包成jar包 一.Spring boot的基本配置 这 ...
- python 模块一(random,counter,defaultdict,time,wraps,reduce) 栈 队列 双向队列
####################总结####################### 模块:你写的py文件 引用其他模块 1.import 模块 2.from 模块 import 功能,类,变量 ...
- 解决mysql:Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)
(一)出现问题的的报错信息 Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111) ( ...
- webService-cxf框架的使用
webService-cxf框架的使用: 1:简介: wbservice常用框架 Axis: --> Axis2 XFire: -->(Web Service框架) XFire是codeH ...
- 简单备份mysql数据库
对于数据量不大的业务场景,可以每天做全量备份. 实现方式:编写备份数据库脚本,然后在crontab中每天定时执行脚本进行备份. 备份脚本示例: #!/bin/bash #Author: zhangsa ...
- Image转Base64
今天和一个朋友联调图片转Base64时发现一个问题 public static string ImageToBase64(Image img) { BinaryFormatter binFormatt ...