首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >编译到字节码,Java和Python。时间差异的原因是什么?

编译到字节码,Java和Python。时间差异的原因是什么?
EN

Stack Overflow用户
提问于 2020-08-13 19:25:20
回答 1查看 2K关注 0票数 4

Java和python (只讨论CPython )分别被解释为Java和CPython字节码。然后,两个字节码都由各自的虚拟机(JVM和Cpython )进行解释。(在这里,我忽略了JIT编译部分,它在10K运行后开始。)

关于这一点,我有两个问题:

  1. 为什么将Java编译成java字节码要比python花费这么多时间?在java中,编译是一个显式步骤,而在python中,编译则发生在运行时。
  2. 为什么第一次运行与第n次运行没有明显的区别,因为在第一次运行中,CPython字节码编译完成并缓存在.pyc文件中,而.pyc文件在所有后续运行中都使用。在python中,这个字节码编译真的是一个几乎零成本的任务吗?

虽然它在运行时中起着很大的作用,但我认为静态和动态类型在编译过程中不应该扮演太大的角色,而且不应该是造成这种时间差异的唯一原因。另外,我认为在这两种实现中,在字节码生成过程中都会进行一些优化。

这里有我遗漏的东西吗?(我在Java方面的工作经验不多。)

更新:

实际上,我对python的第一次运行和之后的运行进行了时间分析,发现语句2是错误的。在运行大型python文件时,有一个非常明显的区别。

方法很简单。创建了一个具有重复行的大型文件。

代码语言:javascript
复制
a = 5
b = 6
c = a*b
print(str(c))

然后将其导入文件large.py并运行time python large.py

第一个运行结果:

代码语言:javascript
复制
python large.py  1.49s user 0.33s system 97% cpu 1.868 total

第二次运行结果:

代码语言:javascript
复制
python large.py  0.20s user 0.08s system 90% cpu 0.312 total

删除__pycache__文件夹后:

代码语言:javascript
复制
python large.py  1.57s user 0.34s system 97% cpu 1.959 total

因此,基本上在python中,字节码的编译是一个昂贵的过程,只是它不像在java中那样昂贵。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-13 21:21:29

Java字节码编译器必须比Python字节码编译器做更多的检查。为了说明这一点,请从"hello world“程序中取这一行:

代码语言:javascript
复制
System.out.println("Hello World!");

要编译这一行代码,编译器必须找到其所有部分的含义。这比听起来要复杂得多:System可以是一个包。或者它可以是一个类,或者在代码所在的包中,或者在导入的包中,或者在java.lang中。所以编译器必须按顺序检查所有这些选项。一旦它找到了System类,它就必须检查它的访问修饰符是否允许这种使用。

之后,编译器必须弄清楚out是什么:它是嵌套类还是类成员,它的访问修饰符是什么?编译器发现它是PrintStream类型的静态成员变量。然后,它必须对println进行同样的检查。编译器不能为这一行代码发出任何代码,除非它知道所有这些,因为生成的字节代码根据所涉及对象的类型不同。

所有这些检查都需要时间,最重要的是因为编译器必须从标准库加载大量的类定义,甚至对于最简单的程序也是如此。

相比之下,Python字节码编译器只需要解析行,它就可以立即生成代码,而无需查看额外的模块。在Python中,代码将被编译为:

从当前作用域( (LOAD_NAME)

  • looking )查找" System“对象( (LOAD_ATTR)

  • looking )中的"out”属性,从"out“(LOAD_METHOD)

  • generate代码中查找"println”属性,将其称为(CALL_METHOD)

Python编译器并不关心这些查找是否在运行时失败。

另一个重要的区别是Java编译器完全用Java编写,并在运行时编译成机器代码,而CPython实现的大部分是提前编译的C代码。这意味着与Python相比,Java有一些“冷启动”问题。

更新:从Java9开始,您可以直接从源代码运行Java程序,而无需将其编译成字节代码。运行一个琐碎的"hello world“程序可以让您了解通过提前将Java编译成字节代码节省了多少钱,甚至对于一个琐碎的程序也是如此:

python程序在45-50毫秒内运行,这是用time python hello.py.

  • The Java程序度量的,但没有提前编译成字节码,运行时间为350-400毫秒,编译成字节码后运行为time java Hello.java

  • The Java程序,运行时间为70-80毫秒,用time java Hello

测量。

免责声明:没有遵循任何科学方法,也没有进行统计分析,因此,以一粒盐来看待这个问题。测试环境:PythonVersion3.8.5,JavaVersion11.0.8,在Fedora 32上,使用Intel i7 8750H CPU

hello.py:

代码语言:javascript
复制
print("hello world")

Hello.java:

代码语言:javascript
复制
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello world");
    }
}
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63401983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档