未编译Python代码比Go慢100倍

2019 年 12 月 06 日

未编译Python代码比Go慢100倍

我是编译型编程语言的忠实粉丝,一直都是。虽然解释型编程语言可以让开发者更快地编写和测试代码,但我仍然认为编译器是值得长期投入的。在我看来,编译型代码有两个明显的优势:


  • 每次修改代码都可以得到验证,甚至是在开始运行代码之前。

  • 更快的执行速度。根据具体情况,代码可能被编译成非常底层的运行指令。


我之所以要写这篇文章,是想比较一下编译型代码的执行速度会比解释型快多少。


因为我偏爱编译型编程语言,所以现在有个问题:我手头有很多感兴趣的代码,但它们都是用 Python 写的,我该怎么办?全部重写?部分重写?完全不重写?


先入之见


在这篇文章里,我通过比较 JavaGoPython 在处理不同任务时的性能表现来验证我对它们的一些先入之见。首先是 Python,我正在考虑要不要把它替换掉。至于 Java,我已经是 20 多年的粉丝了,一路看着它成熟,不管是性能还是功能都在变得更好。最后是 Go,我两年前才开始用它,但真的很喜欢它。虽然 Go 相比 Java 还缺失了一些特性,比如类继承,但它的语法简洁而紧凑,编译和执行速度都很快,生成的代码也很紧凑,还提供了优雅的 goroutine 来实现并发处理。


以下是我的一些先入之见。


  • 编译型代码的执行速度比解释型代码要快一个数量级。之前,我比较了使用 JIT 和不使用 JIT 编译 Java 代码所获得的性能,它们的比率大概是 30 比 1。

  • Go 的运行速度比 Java 要快一点。我记得在之前的工作中做过一些测试,发现 Go 在处理某些任务时要比 Java 快 30%,但最近一些文章又说 Java 比 Go 快。


先来测试一把我在之前的一篇文章中通过一些代码比较过 JIT 的性能,后来使用 Python 和 Go 也实现了一遍。这段代码计算 100 的 Fibonacci 数值,每一轮计算 50 次,并打印执行时间(纳秒),共计算 200 轮。代码可以在GitHub上找到。


三种语言的输出结果看起来像这样:


Java   Go    Python...122    123   11683119    107   11539123    104   11358120    115   11926119    118   11973120    104   11377109    103   12960127    122   15683112    106   11482...
复制代码


平均值是这样:


Java   Go    Python130    105   10050
复制代码


可以看到,在计算 Fibonacci 数值时,Java 比 Go 要慢一些,大概慢 24%,而 Python 几乎慢了 100 倍,也就是 9458%。


这个结果验证了我最初对 Java 和 Go 的判断,但让我感到吃惊的是 Python 的表现,它慢得不只是一个数量级,是两个!


我在想 Python 为什么会花这么多时间。


我首先想到的是,很多人关注的是 Python 的易用性,并通过牺牲性能来快速获得处理结果。我相信数据科学家们都是这么想的。况且有这么多现成的库可以用,为什么要去找其他的?迟早会有人优化它们的。


第二个原因是很多人没有比较过不同的实现,因为很多初创公司在激烈的竞争中忙于做出产品,根本无暇顾及什么优化不优化。


第三个原因,有一些方式可以让同样的 Python 代码跑得更快。


把 Python 代码编译一下会如何


在做了一些调研之后,我决定使用 PyPy 测试一下相同的 Python 代码。PyPy 是 Python 的另一个实现,它本身就是使用 Python 开发的,包含了一个像 Java 那样的 JIT 编译器。跟 Java 一样,我们需要忽略初始的输出,并跳过 JIT 编译过程,得到的结果如下:


Java   Go    Python    PyPy130    105   10050     1887
复制代码


PyPy 的平均响应速度比 Python 快 5 倍,但仍然比 Go 慢 20 倍。


更多的测试


以上的测试主要集中在数值的计算上,如果回到最开始所说的 Python 代码,我还需要关注:


  • Kafka、HTTP 监听器和数据库的 IO;

  • 解析 JSON 消息。


总结


本文通过执行简单的数学运算得出这样的结论:Go 的执行速度比 Java 快一些,比解释运行的 Python 快 2 个数量级。


基于这样的结果,我个人是不会使用 Go 来替换 Java 的。


另一方面,在高负载的关键任务上使用 Python 不是一个好的选择。如果你正面临这种情况,可以考虑使用 Python 编译器作为短期的应急方案。


在决定是否要重写 Python 代码时,还需要考虑到其他因素,比如 IO 和 CPU 方面的问题,但这些超出本文的范围了。


有人提醒我,使用 Go 和 Java 的 64 位整型只能准确计算出 92 的 Fibonacci 数值,再往后会出现溢出(译者:所以代码后来改成了计算 90 的 Fibonacci 数值)。但即使是这样,本文的结论仍然是有效的。


英文原文


Compiled vs interpreted code performance


2019 年 12 月 06 日 14:3116510
用户头像
小智 InfoQ 主编

发布了 395 篇内容, 共 306.9 次阅读, 收获喜欢 1709 次。

关注

评论 3 条评论

发布
用户头像
这个话题在python,建立之初一直都有人进行评论。但是,python还是在它擅长的领域,发挥重要作用,这篇文章,就像用 C++的执行效率,和汇编编写的程序进行性能比较,一点意思都没有
2019 年 12 月 23 日 15:59
回复
用户头像
这么简单的比较性能有何意义?
numba了解下?
2019 年 12 月 18 日 12:02
回复
用户头像
java 和 go 是解决不同的问题的
2019 年 12 月 17 日 16:36
回复
没有更多评论了
发现更多内容

秒懂云通信:选云通信到底哪家强?

巨侠说

云通信 通信云

计算机网络基础(八)---网络层-路由概述

书旅

计算机网络 网络协议 计算机基础 AS

为啥Underlay才是容器网络的最佳落地选择

博云技术社区

云计算 容器 容器网络

Kubernetes的拐点助推器:左手开源,右手边缘计算

华为云开发者社区

Kubernetes 容器 边缘计算 容器技术 华为云

原生Ingress灰度发布能力不够?我们是这么干的

博云技术社区

云计算 容器 云原生 PaaS

进击的 Flink:网易云音乐实时数仓建设实践

Apache Flink

flink

数据湖应用解析:Spark on Elasticsearch一致性问题

华为云开发者社区

大数据 spark elasticsearch 数据湖 华为云

架构训练营第七周作业

张锐

程序设计理念-CentOs7实践Nginx-带来安装服务的通用法则

图南日晟

Nginx PHP-FPM 架构设计 环境安装

架构感悟 7- 性能优化何为

旭东(Frank)

第7周总结:性能

慵秋

面试官拿System.out.println()考了我半个小时?我傻了

Java小咖秀

Java 面试

http请求压测工具

潜默闻雨

挑战10的1,143,913次方种算法组合:这都不是事儿!

华为云开发者社区

华为 算法 进化 华为云

web 性能压测工具

Z冰红茶

来了,来了,你们要的Nginx教程来了

Java旅途

nginx

性能测试与优化 和 操作系统与文件系统

满山李子

极客大学架构师训练营

新手村:MySQL 学习经验、资源的分享

多选参数

MySQL MySQL 高可用 MySQL优化

前浪出新招,996已过时,互联网员工都开始住公司了!(爆公司信息)

程序员生活志

加班 996 007 互联网公司

关于数据库索引的知识点,你所需要了解的都在这儿了

鄙人薛某

MySQL 索引结构 索引 MySQL优化

英特尔唐炯:竞争推动PC行业良性发展,促使英特尔前行

飞天鱼2017

第7周-作业1

seng man

百度人脸算法“飞速迭代”,多模态活体检测V3.1获银行卡检测中心增强级认证

百度大脑

人工智能 人脸识别 百度大脑

【小白学YOLO】YOLOv3网络结构细致解析

华为云开发者社区

人工智能 网络 物体检测 华为云 网络层

PV与UV你的网站也可以

北漂码农有话说

漫画:如何证明sleep不释放锁,而wait释放锁?

王磊

Java Wait Sleep

JVM系列之:String,数组和集合类的内存占用大小

程序那些事

Java JVM GC JOL

直播中那几秒延时到底来自哪?

巨侠说

CDN 云直播 直播 直播带货

BIGO | Likee深度推荐模型的特征工程优化

InfoQ_3597a20b53cc

人工智能

技术​选型的艺术

YourBatman

技术选型 湖北

web压力性能测试

周冬辉

压力测试

未编译Python代码比Go慢100倍-InfoQ