hello stackoverflow用户,这是我提出的第一个问题,所以如果我的表达方式有任何错误,请指出,谢谢
我在Java和C ++中编写了这个简单的计算函数
爪哇:
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)
结果:
爪哇: 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,因为它没有绑定检查
答案 0 :(得分:7)
在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 with
// 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发生在JIT的JVM。我不太了解JAVA,但我认为我不需要打开它们。我知道在GCC上你需要启用优化,当然提前(例如-O2
)
PS:我在21世纪从未使用任何Microsoft编译器,因此我无法帮助您了解如何在其中启用优化。
最后,我不相信这样的微基准是重要的。 Benchmark然后优化您的实际应用程序。
答案 1 :(得分:0)
我的系统上需要大约0.6秒(.592801000秒),Intel 2600K,3.40ghz,MSVC Express 2013,64位模式,标准版本。设置完成后将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;
}
答案 2 :(得分:-1)
我认为描述为什么C / C ++总是比Java更快的最简单的方法是了解Java的工作原理。
从一开始,Java就是为了促进跨平台软件而开发的。在Java之前,必须分别在每个机器系列上编译它们的程序。即使是现在,随着各种硬件架构,公认的标准和操作系统的出现,人们无法克服这一障碍。 Java通过其编译器和JVM实现了这一点。编译器应用它可以进行的任何优化,并将其组装成Java字节码,这类似于编译的优化源的简写。但是,处理器还不能理解这个字节码。
这就是Java虚拟机的用武之地。首先,JVM会确定它运行的环境并加载适当的转换表。然后将字节码读入JVM,并在表格中查找每个代码并将其转换为环境的本机代码,然后执行。
如您所知,每条指令都需要一点点时间。但是使用已编译的C / C ++程序,它已经在正确的机器代码中并立即执行。
有趣的说明 - 出于性能原因,所有操作系统和大多数设备驱动程序都是用C语言编写的。