Java 和 python(仅讨论 CPython)都被分别解释为 Java 和 CPython 字节码。然后,两个字节码都由它们各自的虚拟机(JVM 和 Cpython VM)解释。 (这里我忽略了运行 10K 后启动的 JIT 编译部分。)
我对此有两个问题:
尽管它在运行时中扮演着重要角色,但我认为静态类型与动态类型在编译过程中不应该扮演太大的角色,也不应该是造成这种时序差异的唯一原因。另外,我认为在这两种实现中,在字节码生成期间都会进行一些优化。
我在这里缺少什么吗? (我没有太多使用 Java 的经验。)
更新:
我实际上对 python 第一次运行和后来运行进行了时间分析,发现语句 2 是错误的。运行大型 python 文件时有一个非常明显的区别。
方法很简单。创建了一个带有重复行的大文件
a = 5
b = 6
c = a*b
print(str(c))
然后将其导入文件large.py
并运行 time python large.py
首次运行结果:python large.py 1.49s user 0.33s system 97% cpu 1.868 total
第二次运行结果:python large.py 0.20s user 0.08s system 90% cpu 0.312 total
删除 __pycache__ 文件夹后:python large.py 1.57s user 0.34s system 97% cpu 1.959 total
所以基本上在 python 中,编译为字节码是一个昂贵的过程,只是它不像 java 那样昂贵。
最佳答案
Java 字节码编译器必须比 Python 字节码编译器做更多的检查。为了说明这一点,请从“hello world”程序中提取这一行:
System.out.println("Hello World!");
为了编译这行代码,编译器必须找出它所有部分的含义。这比听起来更复杂:System
可以是一个包。或者它可以是一个类,或者在代码所在的同一个包中,或者在一个导入的包中,或者在 java.lang
中。 .所以编译器必须按顺序检查所有这些选项。一旦找到 System
类,它必须检查它的访问修饰符是否允许这种使用。之后,编译器必须弄清楚
out
是什么是:它是一个嵌套类,还是一个类成员,它的访问修饰符是什么?编译器发现它是 PrintStream
的静态成员变量。类型。然后它必须对 println
进行相同的检查。 .编译器在知道所有这些之前不能为这行代码发出任何代码,因为生成的字节码根据所涉及的对象的类型而有所不同。所有这些检查都需要时间,最重要的是,即使对于最简单的程序,编译器也必须从标准库中加载大量的类定义。
相比之下,Python字节码编译器只需要解析一行,就可以立即生成代码,无需查看额外的模块。在 Python 中,代码将被编译为:
Python 编译器并不关心其中一些查找是否在运行时失败。
另一个重要的区别是 Java 编译器完全用 Java 编写,并在运行时编译为机器代码,而大部分 CPython 实现是提前编译的 C 代码。这意味着与 Python 相比,Java 存在一些“冷启动”问题。
更新:从 Java 9 开始,您可以直接从源代码运行 Java 程序,而无需将其编译为字节码。运行一个简单的“hello world”程序可以让您了解通过提前将 Java 编译为字节码可以节省多少,即使对于一个简单的程序也是如此:
time python hello.py
测量,python 程序运行时间为 45-50 毫秒。 . time java Hello.java
测量。 time java Hello
测量。 免责声明:没有遵循科学方法或进行统计分析,因此请谨慎对待。测试环境:Python 3.8.5,Java 11.0.8,Fedora 32,Intel i7 8750H CPU
你好.py:
print("hello world")
你好.java:public class Hello {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
关于java - 编译为字节码,Java 与 Python。所用时间不同的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63401983/