为什么这个简单的C加法比同等的Java慢6倍?

你好*用户,这是我提出的第一个问题,所以如果我的表达方式有任何错误,请指出,谢谢

我在Java和C中编写了这个简单的计算函数

Java的:

long start = System.nanoTime();
long total = 0;
for (int i = 0; i < 2147483647; i++) {
    total += i;
}
System.out.println(total);
System.out.println(System.nanoTime() - start);

C :

auto start = chrono::high_resolution_clock::now();
register long long total = 0;
for (register int i = 0; i < 2147483647; i++)
{
    total += i;
}
cout << total << endl;
auto finish = chrono::high_resolution_clock::now();
cout << chrono::duration_cast<chrono::nanoseconds>(finish - start).count() << endl;

软件:
– JDK8u11
– Microsoft Visual C编译器(2013)

结果:

Java的:
2305843005992468481
1096361110

C :
2305843005992468481
6544374300

计算结果相同,这很好
然而,打印的纳米时间显示Java程序需要1秒,而在C中需要6秒执行

我已经做了很长一段时间的Java,但我是C的新手,我的代码有什么问题吗?或者通过简单的计算,C比Java慢?

另外,我在我的C代码中使用了“register”关键字,希望它能带来性能提升,但执行时间完全没有差异,有人可以解释一下吗?

编辑:我的错误是C编译器设置没有优化,输出设置为x32,应用/ O2 WIN64并删除DEBUG后,程序只花了0.7秒执行

JDK默认情况下对输出应用优化,但是VC不是这种情况,默认情况下有利于编译速度,不同的C编译器的结果也不同,有些会在编译时计算循环的结果,导致执行时间极短(大约5微秒)

注意:在适当的条件下,C程序在这个简单的测试中将比Java执行得更好,但是我注意到跳过了很多运行时安全检查,违反了它作为“安全语言”的调试意图,我相信C在性能上会优于Java一个大型数组测试,因为它没有绑定检查

解决方法:

在Linux / Debian / Sid / x86-64上,使用OpenJDK 7

// file test.java
class Test {
    public static void main(String[] args) {
    long start = System.nanoTime();
    long total = 0;
    for (int i = 0; i < 2147483647; i++) {
        total += i;
    }
    System.out.println(total);
    System.out.println(System.nanoTime() - start);
    }
}   

和GCC 4.9

   // file test.cc
#include <iostream>
#include <chrono>

int main (int argc, char**argv) {
 using namespace std;
 auto start = chrono::high_resolution_clock::now();
 long long total = 0;
 for (int i = 0; i < 2147483647; i++)
   {
     total += i;
   }
 cout << total << endl;
 auto finish = chrono::high_resolution_clock::now();
 cout << chrono::duration_cast<chrono::nanoseconds>(finish - start).count()
      << endl;
}    

然后编译并运行test.java

javac test.java
java Test

我得到了输出

2305843005992468481
774937152

何时使用优化编译test.cc

g++ -O2 -std=c++11 test.cc -o test-gcc

并且运行./test-gcc它变得更快

2305843005992468481
40291

当然没有优化g -std = c 11 test.cc -o test-gcc运行速度较慢

2305843005992468481
5208949116

通过使用g -O2 -fverbose-asm -S -std = c 11 test.cc查看汇编代码,我看到编译器在编译时计算了结果:

    .globl  main
    .type   main, @function
  main:
  .LFB1530:
    .cfi_startproc
    pushq   %rbx    #
    .cfi_def_cfa_offset 16
    .cfi_offset 3, -16
    call    _ZNSt6chrono3_V212system_clock3nowEv    #
    movabsq $2305843005992468481, %rsi  #,
    movl    $_ZSt4cout, %edi    #,
    movq    %rax, %rbx  #, start
    call    _ZNSo9_M_insertIxEERSoT_    #
    movq    %rax, %rdi  # D.35007,
    call    _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_  #
    call    _ZNSt6chrono3_V212system_clock3nowEv    #
    subq    %rbx, %rax  # start, D.35008
    movl    $_ZSt4cout, %edi    #,
    movq    %rax, %rsi  # D.35008, D.35008
    call    _ZNSo9_M_insertIlEERSoT_    #
    movq    %rax, %rdi  # D.35007,
    call    _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_  #
    xorl    %eax, %eax  #
    popq    %rbx    #
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
  .LFE1530:
            .size   main, .-main

所以你只需要在编译器中启用优化(或切换到更好的编译器,如GCC 4.9)

关于Java低级优化的BTW发生在0700的JIT.我不太了解JAVA,但我不认为我需要打开它们.我知道在GCC上你需要启用优化,这当然是提前的(例如使用-O2)

PS:我在21世纪从未使用任何Microsoft编译器,因此我无法帮助您了解如何在其中启用优化.

最后,我不相信这样的微基准是重要的. Benchmark然后优化您的实际应用程序.

上一篇:Javascript将数字添加为字符串


下一篇:Java中的整数加法性能