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

为什么这个简单的C++;添加速度比等效Java慢6倍?,java,c++,performance,addition,nanotime,Java,C++,Performance,Addition,Nanotime,stackoverflow用户您好,这是我问的第一个问题,所以如果我的表达方式有任何错误,请指出,谢谢 我用Java和C编写了这个简单的计算函数++ 爪哇: long start=System.nanoTime(); 长总计=0; 对于(int i=0;i

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

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

爪哇:

long start=System.nanoTime();
长总计=0;
对于(int i=0;i<2147483647;i++){
总数+=i;
}
系统输出打印项次(总计);
System.out.println(System.nanoTime()-start);
C++:

auto start=chrono::high_resolution_clock::now();
寄存器长总计=0;
用于(寄存器int i=0;i<2147483647;i++)
{
总数+=i;
}

在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);
    }
}   
我正在得到输出

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
因此,您只需在编译器中启用优化(或切换到更好的编译器,如4.9)

顺便说一句,Java底层优化发生在。我不太懂JAVA,但我认为我不需要打开它们。我确实知道,在GCC上,您需要启用优化,这当然是提前的(例如使用
-O2

PS:在这个21世纪,我从来没有使用过任何微软编译器,所以我无法帮助您实现优化

最后,我不相信这些微基准是有意义的。基准测试然后优化实际应用程序。

在我的系统上,英特尔2600K,3.40ghz,采用MSVC Express 2013,64位模式,标准版本构建,大约需要0.6秒(.592801000秒)。设置完成后将cout移至,以不包括cout的开销

#include <iostream>
#include <chrono>

using namespace std;

int main()
{
    auto start = chrono::high_resolution_clock::now();
    register long long total = 0;
    for (register int i = 0; i < 2147483647; i++)
    {
        total += i;
    }
    auto finish = chrono::high_resolution_clock::now();
    cout << total << endl;
    cout << chrono::duration_cast<chrono::nanoseconds>(finish - start).count() << endl;
    return 0;
}
#包括
#包括
使用名称空间std;
int main()
{
自动启动=时钟::高分辨率时钟::现在();
寄存器长总计=0;
用于(寄存器int i=0;i<2147483647;i++)
{
总数+=i;
}
自动完成=时钟::高分辨率时钟::现在();

我认为描述为什么C/C++总是比Java快的最简单方法是理解Java是如何工作的

从一开始,Java就是为了方便跨平台软件而开发的。在Java出现之前,人们必须在每个机器系列上分别编译程序。即使是现在,由于硬件体系结构、公认标准和操作系统的多样性,人们也无法绕过这一障碍。Java通过其编译器和JV实现这一点M.编译器应用它所能应用的任何优化,并将其汇编成Java字节码,这就像编译的优化源代码的简写。然而,处理器还不能理解这个字节码

这就是Java虚拟机的用武之地。首先,JVM计算出它在什么环境中运行,并加载相应的转换表。然后,字节码被读入JVM,每个代码都在表中查找并转换为环境的本机代码,然后执行

正如你所知,这一切都需要一点点的时间,但对于一个已编译的C/C++程序,它已经在正确的机器代码中,并立即执行


有趣的注意事项-出于性能原因,所有操作系统和大多数设备驱动程序都是用C编写的。

您是如何编译的?使用哪种编译器和优化标志?在哪种系统上?
寄存器在C++11中被弃用,并且通常被编译器忽略。可能是I/O-在打印总数之前需要完成时间。我的测试显示G++完全在代码> > O0以上的任何一个地方完全绕过循环。或者C++是比java简单的计算慢的事实吗?不,这是肯定的。对java来说,它不必切换优化。相反,它是不可能的(或者非常复杂)。“OP:在未优化C++和未优化Java之间的比较中,C++将更快地被使用,因为JVM是用……写的。如果没有优化,JVM开销只是处理器=慢的更多工作。@ DeavangFeNe:只要JIT技术使用java语言,JVM编码的语言就不相关了。动态生成机器代码。性能与JIT发出的机器代码的质量有关,JVM发出的机器代码发生在运行时。“没有”任何优化技术…?在我看来,这也包括提高JIT的机器代码质量。根据定义,JVM和JIT正在进行一些优化。我明白你的意思了,现在我添加了/O2/GL标志,相同的代码需要1.7秒才能执行。速度要快得多,但为什么它仍然比Java慢?但它没有预热JITC。“出于性能原因,所有操作系统和大多数设备驱动程序都是用C编写的。“这不是真的。真的吗?那么请告诉我Java是如何工作的。请告诉我哪些操作系统或驱动程序不是用C编写的?也不要不尊重这些板上的人。许多IBM机箱的操作系统是用PL/S编写的。我个人编写了很多JVM(包括解释器、验证器和“静态解释器”)用于IBM iSeries版本的Java,因此我对Java的工作原理有了比您更好的了解。
2305843005992468481
40291
2305843005992468481
5208949116
    .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
#include <iostream>
#include <chrono>

using namespace std;

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