因此,我们都知道,Java解释缓慢且C的编译和优化运行速度非常快。 您可能知道,图片截然不同。
TL; DR Java适用于星座,它的速度更快,因为JIT可以执行内联,因为所有方法/功能都是可见的,而C编译器无法跨编译单元(例如库等)执行优化。
一次写入,随处运行
写一次,到处等待 ”,因为解释器会很慢。 因此,现代JVM要做的就是及时编译。 这意味着JVM在内部将字节码转换为用于CPU的机器代码。 但是由于此过程非常复杂,因此Hotspot JVM (最常用的一种)仅对经常执行的代码片段执行此操作(因此命名为Hotspot
现在,在查看我的完整示例之前,请注意,Java具有许多功能,例如动态调度(在接口上调用方法),它还带有运行时开销。 因此,Java代码可能更容易编写,但通常仍会比C代码慢。 但是,当涉及纯数字运算时,就像下面的示例一样,有一些有趣的发现。
因此,无需进一步讨论,这是示例C代码:
test.c:
int compute(int i);
int test(int i);
int main(int argc, char** argv) {
int sum = 0;
for(int l = 0; l < 1000; l++) {
int i = 0;
while(i < 2000000) {
if (test(i))
sum += compute(i);
i++;
}
}
return sum;
}
test1.c:
int compute(int i) {
return i + 1;
}
int test(int i) {
return i % 3;
}
现在,主要功能的实际计算完全不重要。 关键是它经常调用两个函数(测试和计算),并且这些函数在另一个编译单元(test1.c)中。 现在让我们编译并运行程序:
> gcc -O2 -c test1.c
> gcc -O2 -c test.c
> gcc test.o test1.o
> time ./a.out
real 0m6.693s
user 0m6.674s
sys 0m0.012s
6.6秒
Test.java
public class Test {
private static int test(int i) {
return i % 3; }
private static int compute(int i) {
return i + 1; }
private static int exec() {
int sum = 0; for (int l = 0; l < 1000; l++) {
int i = 0; while (i < 2000000) {
if (test(i) != 0) {
sum += compute(i); }
i++; }
}
return sum; }
public static void main(String[] args) {
exec(); }
}
现在让我们编译并执行以下命令:
> javac Test.java
> time java Test
real 0m3.411s
user 0m3.395s
sys 0m0.030s
3.4秒的时间
那么,这是一个在现实生活中从未发生过的完全异国情调的虚构例子吗? 是的,没有。 当然,这是一个极端的情况,但是请考虑一下代码中包含的所有库。 所有这些方法都不能在C语言中进行优化,而在Java中,字节码的来源无关紧要。 由于所有JIT都存在于正在运行的JVM中,因此JIT可以对其核心内容进行优化。 当然,C语言有一个卑鄙的技巧可以减轻这种痛苦:Marcos。 在我看来,这就是市长的原因之一,为什么C中如此之多的库仍然使用宏而不是适当的功能-伴随着它们带来的所有问题和麻烦。
现在就在火焰战争开始之前:这两种语言都有其长处和短处,并且在软件工程领域都占有一席之地。 撰写这篇文章仅是为了吸引您的注意,并想知道现代JVM每天都在发生。