java - 为什么这个简单的 C++ 添加比等效的 Java 慢 6 倍?

标签 java c++ performance addition nanotime

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

我用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 - 微软 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 低级优化发生在 JIT 中的 JVM .我不太了解 JAVA,但我认为我不需要打开它们。我知道在 GCC 上你需要启用优化,这当然是提前(例如使用 -O2)

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

最后,我不认为这样的微基准测试很重要。基准然后优化您的实际应用程序。

关于java - 为什么这个简单的 C++ 添加比等效的 Java 慢 6 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24848062/

相关文章:

c++ - 意外的 std::io_base::failure 异常

c# - SQlBulkCopy 数据源中DateTime类型的给定值无法转换为指定目标列的int类型

mysql - 如何加快该查询(子选择)的执行速度?

java - 如何使用点击处理程序隐藏 GWT PopupPanel?

c++ - Eclipse CDT - 为什么它要构建我创建的文件的拷贝?

java - 使用hibernate将 map 插入数据库

c++ - 从 C++ 调用静态 C++/CLI 方法

ruby - ruby 在线快速计算环境

java - 方法 sort(Map<Integer,Object>) 不适用于参数 (Map<Integer,Entity>)

Java Swing : Picture size doesn't update on resize