java 代码运行速度慢_C代码的运行速度总是比Java快,对吧? 错误!

java 代码运行速度慢

因此,我们都知道,Java解释缓慢且C的编译和优化运行速度非常快。 您可能知道,情况截然不同。

TL; DR Java适用于星座图,它的速度更快,在JIT上可以执行内联,因为所有方法/功能都是可见的,而C编译器无法跨编译单元(例如库等)执行优化。

AC编译器将C代码作为输入,对其进行编译和优化,并生成要执行的特定CPU或体系结构的机器代码。 这导致可执行文件,无需进一步步骤即可直接在给定计算机上运行。 另一方面,Java有一个中间步骤:字节码。 因此,Java编译器将Java代码作为输入并生成字节码,而字节码基本上是抽象机的机器代码。 现在,对于每个(流行的)CPU架构,都有一个Java Virual机器,该机器模拟此抽象机器并执行(解释)生成的字节码。 这听起来很慢。 但是另一方面,字节码是可移植的,因为相同的输出将在所有平台上运行,因此口号“ 一次写入,随处运行 ”。

现在,使用上述方法,它会变成“ 编写一次,到处等待 ”,因为解释器会很慢。 因此,现代JVM所做的只是及时编译。 这意味着JVM在内部将字节码转换为用于CPU的机器代码。 但是由于此过程非常复杂,因此Hotspot JVM (最常用的一种)仅对经常执行的代码片段执行此操作(因此命名为Hotspot )。 除了更快地启动(解释器立即启动,JIT编译器根据需要启动)之外,还有另一个好处:热点JIT已经知道代码的哪些部分被频繁调用,什么不被调用-因此它可以在优化输出时使用它–这就是我们的例子发挥作用的地方。

现在,在看我完整的微型示例之前,请注意,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秒 。 现在让我们看一下Java程序:

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秒的时间 ,Java可以轻松完成此简单任务(甚至包括JVM的缓慢启动)。 问题是为什么? 当然,答案是JIT可以执行C编译器无法执行的代码优化。 在我们的例子中是函数内联。 当我们在自己的编译单元中定义了我们的两个微型函数时,编译器无法在编译test.c时内联这些函数。另一方面,JIT拥有所有方法,并且可以执行主动内联,因此编译后的代码速度更快。

那么,这是一个在现实生活中从未发生过的完全异国情调的虚构例子吗? 是的,没有。 当然,这是一个极端的情况,但是请考虑一下代码中包含的所有库。 所有这些方法都不能在C语言中进行优化,而在Java中,字节码的来源无关紧要。 由于所有这些都存在于正在运行的JVM中,因此JIT可以对其核心内容进行优化。 当然,C语言有一个肮脏的技巧可以减轻这种痛苦:Marcos。 在我看来,这就是市长的原因之一,为什么C中如此之多的库仍然使用宏而不是适当的功能-伴随着它们带来的所有问题和麻烦。

现在就在火焰战争开始之前:这两种语言都有其长处和短处,并且在软件工程领域都占有一席之地。 这篇文章的撰写仅是为了吸引您的魔力,并想知道现代JVM每天都在发生。

翻译自: https://www.javacodegeeks.com/2016/02/c-code-always-runs-way-faster-java-right-wrong.html

java 代码运行速度慢

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值